1
1
#!/usr/bin/env python3
2
2
from __future__ import annotations
3
3
4
+ import logging
4
5
import argparse
5
6
import os
6
7
import struct
14
15
sys .path .insert (1 , str (Path (__file__ ).parent / 'gguf-py' ))
15
16
import gguf
16
17
18
+ logger = logging .getLogger ("ggml-to-gguf" )
19
+
17
20
18
21
class GGMLFormat (IntEnum ):
19
22
GGML = 0
@@ -125,7 +128,7 @@ def load(self, data, offset):
125
128
self .start_offset = offset
126
129
self .len_bytes = n_bytes
127
130
offset += n_bytes
128
- # print (n_dims, name_len, dtype, self.dims, self.name, pad)
131
+ # logger.info (n_dims, name_len, dtype, self.dims, self.name, pad)
129
132
return offset - orig_offset
130
133
131
134
@@ -175,7 +178,7 @@ def load(self, data, offset):
175
178
offset += self .validate_header (data , offset )
176
179
hp = Hyperparameters ()
177
180
offset += hp .load (data , offset )
178
- print (f'* File format: { self .file_format .name } v{ self .format_version } with ftype { hp .ftype .name } ' )
181
+ logger . info (f'* File format: { self .file_format .name } v{ self .format_version } with ftype { hp .ftype .name } ' )
179
182
self .validate_conversion (hp .ftype )
180
183
vocab = Vocab (load_scores = self .file_format > GGMLFormat .GGML )
181
184
offset += vocab .load (data , offset , hp .n_vocab )
@@ -215,12 +218,12 @@ def __init__(self, ggml_model, data, cfg, params_override = None, vocab_override
215
218
if float (hp .n_head ) / float (x ) == gqa :
216
219
n_kv_head = x
217
220
assert n_kv_head is not None , "Couldn't determine n_kv_head from GQA param"
218
- print (f'- Guessed n_kv_head = { n_kv_head } based on GQA { cfg .gqa } ' )
221
+ logger . info (f'- Guessed n_kv_head = { n_kv_head } based on GQA { cfg .gqa } ' )
219
222
self .n_kv_head = n_kv_head
220
223
self .name_map = gguf .get_tensor_name_map (gguf .MODEL_ARCH .LLAMA , ggml_model .hyperparameters .n_layer )
221
224
222
225
def save (self ):
223
- print ('* Preparing to save GGUF file' )
226
+ logger . info ('* Preparing to save GGUF file' )
224
227
gguf_writer = gguf .GGUFWriter (
225
228
self .cfg .output ,
226
229
gguf .MODEL_ARCH_NAMES [gguf .MODEL_ARCH .LLAMA ],
@@ -230,11 +233,11 @@ def save(self):
230
233
if self .special_vocab is not None :
231
234
self .special_vocab .add_to_gguf (gguf_writer )
232
235
self .add_tensors (gguf_writer )
233
- print (" gguf: write header" )
236
+ logger . info (" gguf: write header" )
234
237
gguf_writer .write_header_to_file ()
235
- print (" gguf: write metadata" )
238
+ logger . info (" gguf: write metadata" )
236
239
gguf_writer .write_kv_data_to_file ()
237
- print (" gguf: write tensors" )
240
+ logger . info (" gguf: write tensors" )
238
241
gguf_writer .write_tensors_to_file ()
239
242
gguf_writer .close ()
240
243
@@ -250,7 +253,7 @@ def add_params(self, gguf_writer):
250
253
name = cfg .name if cfg .name is not None else cfg .input .name
251
254
except UnicodeDecodeError :
252
255
name = None
253
- print ('* Adding model parameters and KV items' )
256
+ logger . info ('* Adding model parameters and KV items' )
254
257
if name is not None :
255
258
gguf_writer .add_name (name )
256
259
gguf_writer .add_description (desc )
@@ -286,7 +289,7 @@ def add_vocab(self, gguf_writer):
286
289
toktypes = []
287
290
if self .vocab_override is not None :
288
291
vo = self .vocab_override
289
- print ('* Adding vocab item(s)' )
292
+ logger . info ('* Adding vocab item(s)' )
290
293
for (idx , (vbytes , score , ttype )) in enumerate (vo .all_tokens ()):
291
294
tokens .append (vbytes )
292
295
scores .append (score )
@@ -298,7 +301,7 @@ def add_vocab(self, gguf_writer):
298
301
if len (toktypes ) > 0 :
299
302
gguf_writer .add_token_types (toktypes )
300
303
return
301
- print (f'* Adding { hp .n_vocab } vocab item(s)' )
304
+ logger . info (f'* Adding { hp .n_vocab } vocab item(s)' )
302
305
assert len (self .model .vocab .items ) >= 3 , 'Cannot handle unexpectedly short model vocab'
303
306
for (tokid , (vbytes , vscore )) in enumerate (self .model .vocab .items ):
304
307
tt = 1 # Normal
@@ -333,7 +336,7 @@ def add_vocab(self, gguf_writer):
333
336
def add_tensors (self , gguf_writer ):
334
337
tensor_map = self .name_map
335
338
data = self .data
336
- print (f'* Adding { len (self .model .tensors )} tensor(s)' )
339
+ logger . info (f'* Adding { len (self .model .tensors )} tensor(s)' )
337
340
for tensor in self .model .tensors :
338
341
name = str (tensor .name , 'UTF-8' )
339
342
mapped_name = tensor_map .get_name (name , try_suffixes = (".weight" , ".bias" ))
@@ -343,7 +346,7 @@ def add_tensors(self, gguf_writer):
343
346
temp = tempdims [1 ]
344
347
tempdims [1 ] = tempdims [0 ]
345
348
tempdims [0 ] = temp
346
- # print (f'+ {tensor.name} | {mapped_name} {tensor.dims} :: {tempdims}')
349
+ # logger.info (f'+ {tensor.name} | {mapped_name} {tensor.dims} :: {tempdims}')
347
350
gguf_writer .add_tensor (
348
351
mapped_name ,
349
352
data [tensor .start_offset :tensor .start_offset + tensor .len_bytes ],
@@ -400,41 +403,46 @@ def handle_args():
400
403
help = "directory containing tokenizer.model, if separate from model file - only meaningful with --model-metadata-dir" )
401
404
parser .add_argument ("--vocabtype" , default = "spm,hfft" ,
402
405
help = "vocab format - only meaningful with --model-metadata-dir and/or --vocab-dir (default: spm,hfft)" )
406
+ parser .add_argument ("--verbose" , action = "store_true" , help = "increase output verbosity" )
403
407
return parser .parse_args ()
404
408
405
409
406
410
def main ():
407
411
cfg = handle_args ()
408
- print (f'* Using config: { cfg } ' )
409
- print ('\n === WARNING === Be aware that this conversion script is best-effort. Use a native GGUF model if possible. === WARNING ===\n ' )
412
+ if cfg .verbose :
413
+ logging .basicConfig (level = logging .DEBUG )
414
+ else :
415
+ logging .basicConfig (level = logging .INFO )
416
+ logger .info (f'* Using config: { cfg } ' )
417
+ logger .warning ('=== WARNING === Be aware that this conversion script is best-effort. Use a native GGUF model if possible. === WARNING ===' )
410
418
if cfg .model_metadata_dir is None and (cfg .gqa == 1 or cfg .eps == '5.0e-06' ):
411
- print ('- Note: If converting LLaMA2, specifying "--eps 1e-5" is required. 70B models also need "--gqa 8".' )
419
+ logger . info ('- Note: If converting LLaMA2, specifying "--eps 1e-5" is required. 70B models also need "--gqa 8".' )
412
420
data = np .memmap (cfg .input , mode = 'r' )
413
421
model = GGMLModel ()
414
- print ('* Scanning GGML input file' )
422
+ logger . info ('* Scanning GGML input file' )
415
423
offset = model .load (data , 0 ) # noqa
416
- print (f'* GGML model hyperparameters: { model .hyperparameters } ' )
424
+ logger . info (f'* GGML model hyperparameters: { model .hyperparameters } ' )
417
425
vocab_override = None
418
426
params_override = None
419
427
special_vocab = None
420
428
if cfg .model_metadata_dir is not None :
421
429
(params_override , vocab_override , special_vocab ) = handle_metadata (cfg , model .hyperparameters )
422
- print ('!! Note: When overriding params the --gqa, --eps and --context-length options are ignored.' )
423
- print (f'* Overriding params: { params_override } ' )
424
- print (f'* Overriding vocab: { vocab_override } ' )
425
- print (f'* Special vocab: { special_vocab } ' )
430
+ logger . info ('!! Note: When overriding params the --gqa, --eps and --context-length options are ignored.' )
431
+ logger . info (f'* Overriding params: { params_override } ' )
432
+ logger . info (f'* Overriding vocab: { vocab_override } ' )
433
+ logger . info (f'* Special vocab: { special_vocab } ' )
426
434
else :
427
- print ('\n === WARNING === Special tokens may not be converted correctly. Use --model-metadata-dir if possible === WARNING ===\n ' )
435
+ logger . warning ('\n === WARNING === Special tokens may not be converted correctly. Use --model-metadata-dir if possible === WARNING ===\n ' )
428
436
if model .file_format == GGMLFormat .GGML :
429
- print ('! This is a very old GGML file that does not contain vocab scores. Strongly recommend using model metadata!' )
437
+ logger . info ('! This is a very old GGML file that does not contain vocab scores. Strongly recommend using model metadata!' )
430
438
converter = GGMLToGGUF (
431
439
model , data , cfg ,
432
440
params_override = params_override ,
433
441
vocab_override = vocab_override ,
434
442
special_vocab = special_vocab
435
443
)
436
444
converter .save ()
437
- print (f'* Successful completion. Output saved to: { cfg .output } ' )
445
+ logger . info (f'* Successful completion. Output saved to: { cfg .output } ' )
438
446
439
447
440
448
if __name__ == '__main__' :
0 commit comments