@@ -48,7 +48,7 @@ class Model:
48
48
49
49
dir_model : Path
50
50
ftype : gguf .LlamaFileType
51
- fname_out : Path | None
51
+ fname_out : Path
52
52
is_big_endian : bool
53
53
endianess : gguf .GGUFEndian
54
54
use_temp_file : bool
@@ -62,11 +62,12 @@ class Model:
62
62
gguf_writer : gguf .GGUFWriter
63
63
model_name : str | None
64
64
metadata_override : Path | None
65
+ dir_model_card : Path
65
66
66
67
# subclasses should define this!
67
68
model_arch : gguf .MODEL_ARCH
68
69
69
- def __init__ (self , dir_model : Path , ftype : gguf .LlamaFileType , fname_out : Path | None , is_big_endian : bool = False ,
70
+ def __init__ (self , dir_model : Path , ftype : gguf .LlamaFileType , fname_out : Path , is_big_endian : bool = False ,
70
71
use_temp_file : bool = False , eager : bool = False ,
71
72
metadata_override : Path | None = None , model_name : str | None = None ,
72
73
split_max_tensors : int = 0 , split_max_size : int = 0 , dry_run : bool = False , small_first_shard : bool = False ):
@@ -90,6 +91,7 @@ def __init__(self, dir_model: Path, ftype: gguf.LlamaFileType, fname_out: Path |
90
91
self .tensor_names = None
91
92
self .metadata_override = metadata_override
92
93
self .model_name = model_name
94
+ self .dir_model_card = dir_model # overridden in convert_lora_to_gguf.py
93
95
94
96
# Apply heuristics to figure out typical tensor encoding based on first layer tensor encoding type
95
97
if self .ftype == gguf .LlamaFileType .GUESSED :
@@ -345,7 +347,7 @@ def prepare_metadata(self, vocab_only: bool):
345
347
346
348
total_params , shared_params , expert_params , expert_count = self .gguf_writer .get_total_parameter_count ()
347
349
348
- self .metadata = gguf .Metadata .load (self .metadata_override , self .dir_model , self .model_name , total_params )
350
+ self .metadata = gguf .Metadata .load (self .metadata_override , self .dir_model_card , self .model_name , total_params )
349
351
350
352
# Fallback to model directory name if metadata name is still missing
351
353
if self .metadata .name is None :
@@ -359,27 +361,22 @@ def prepare_metadata(self, vocab_only: bool):
359
361
output_type : str = self .ftype .name .partition ("_" )[2 ]
360
362
361
363
# Filename Output
362
- # Note: `not is_dir()` is used because `.is_file()` will not detect
363
- # file template strings as it doesn't actually exist as a file
364
- if self .fname_out is not None and not self .fname_out .is_dir ():
365
- # Output path is a custom defined templated filename
366
-
367
- # Process templated file name with the output ftype, useful with the "auto" ftype
368
- self .fname_out = self .fname_out .parent / gguf .fill_templated_filename (self .fname_out .name , output_type )
369
- else :
364
+ if self .fname_out .is_dir ():
370
365
# Generate default filename based on model specification and available metadata
371
366
if not vocab_only :
372
367
fname_default : str = gguf .naming_convention (self .metadata .name , self .metadata .basename , self .metadata .finetune , self .metadata .version , self .metadata .size_label , output_type , model_type = "LoRA" if total_params < 0 else None )
373
368
else :
374
369
fname_default : str = gguf .naming_convention (self .metadata .name , self .metadata .basename , self .metadata .finetune , self .metadata .version , size_label = None , output_type = None , model_type = "vocab" )
375
370
376
- # Check if preferred output directory path was provided
377
- if self .fname_out is not None and self .fname_out .is_dir ():
378
- # output path is a directory
379
- self .fname_out = self .fname_out / f"{ fname_default } .gguf"
380
- else :
381
- # output in the same directory as the model by default
382
- self .fname_out = self .dir_model / f"{ fname_default } .gguf"
371
+ # Use the default filename
372
+ self .fname_out = self .fname_out / f"{ fname_default } .gguf"
373
+ else :
374
+ # Output path is a custom defined templated filename
375
+ # Note: `not is_dir()` is used because `.is_file()` will not detect
376
+ # file template strings as it doesn't actually exist as a file
377
+
378
+ # Process templated file name with the output ftype, useful with the "auto" ftype
379
+ self .fname_out = self .fname_out .parent / gguf .fill_templated_filename (self .fname_out .name , output_type )
383
380
384
381
self .set_type ()
385
382
@@ -596,6 +593,9 @@ def get_vocab_base_pre(self, tokenizer) -> str:
596
593
if chkhsh == "7b3e7548e4308f52a76e8229e4e6cc831195d0d1df43aed21ac6c93da05fec5f" :
597
594
# ref: https://huggingface.co/WisdomShell/CodeShell-7B
598
595
res = "codeshell"
596
+ if chkhsh == "63b97e4253352e6f357cc59ea5b583e3a680eaeaf2632188c2b952de2588485e" :
597
+ # ref: https://huggingface.co/mistralai/Mistral-Nemo-Base-2407
598
+ res = "tekken"
599
599
600
600
if res is None :
601
601
logger .warning ("\n " )
@@ -753,7 +753,8 @@ def _create_vocab_sentencepiece(self):
753
753
token_id = int (token_id )
754
754
token : str = token_data ["content" ]
755
755
if toktypes [token_id ] != SentencePieceTokenTypes .UNUSED :
756
- assert tokens [token_id ] == token .encode ("utf-8" )
756
+ if tokens [token_id ] != token .encode ("utf-8" ):
757
+ logger .warning (f'replacing token { token_id } : { tokens [token_id ].decode ("utf-8" )!r} -> { token !r} ' )
757
758
if token_data .get ("special" ) or self .does_token_look_special (token ):
758
759
toktypes [token_id ] = SentencePieceTokenTypes .CONTROL
759
760
else :
@@ -1312,6 +1313,7 @@ def set_vocab(self):
1312
1313
special_vocab ._set_special_token ("prefix" , 1 )
1313
1314
special_vocab ._set_special_token ("suffix" , 3 )
1314
1315
special_vocab ._set_special_token ("middle" , 2 )
1316
+ special_vocab .chat_template = None # do not add it twice
1315
1317
special_vocab .add_to_gguf (self .gguf_writer )
1316
1318
1317
1319
def set_gguf_parameters (self ):
@@ -2014,7 +2016,8 @@ def set_vocab(self):
2014
2016
token_id = int (token_id )
2015
2017
token = foken_data ["content" ].encode ("utf-8" )
2016
2018
if toktypes [token_id ] != SentencePieceTokenTypes .UNUSED :
2017
- assert tokens [token_id ] == token
2019
+ if tokens [token_id ] != token :
2020
+ logger .warning (f'replacing token { token_id } : { tokens [token_id ].decode ("utf-8" )!r} -> { token .decode ("utf-8" )!r} ' )
2018
2021
tokens [token_id ] = token
2019
2022
scores [token_id ] = - 1000.0
2020
2023
toktypes [token_id ] = SentencePieceTokenTypes .USER_DEFINED
@@ -2030,7 +2033,8 @@ def set_vocab(self):
2030
2033
token_id = int (foken_data ["id" ])
2031
2034
token = foken_data ["content" ].encode ("utf-8" )
2032
2035
if toktypes [token_id ] != SentencePieceTokenTypes .UNUSED :
2033
- assert tokens [token_id ] == token
2036
+ if tokens [token_id ] != token :
2037
+ logger .warning (f'replacing token { token_id } : { tokens [token_id ].decode ("utf-8" )!r} -> { token .decode ("utf-8" )!r} ' )
2034
2038
tokens [token_id ] = token
2035
2039
scores [token_id ] = - 1000.0
2036
2040
toktypes [token_id ] = SentencePieceTokenTypes .USER_DEFINED
@@ -2269,7 +2273,8 @@ def set_vocab(self):
2269
2273
chat_eos_token_id = token_id
2270
2274
token = token .encode ("utf-8" )
2271
2275
if toktypes [token_id ] != SentencePieceTokenTypes .UNUSED :
2272
- assert (tokens [token_id ] == token )
2276
+ if tokens [token_id ] != token :
2277
+ logger .warning (f'replacing token { token_id } : { tokens [token_id ].decode ("utf-8" )!r} -> { token .decode ("utf-8" )!r} ' )
2273
2278
tokens [token_id ] = token
2274
2279
scores [token_id ] = - 1000.0
2275
2280
toktypes [token_id ] = SentencePieceTokenTypes .USER_DEFINED
@@ -2288,7 +2293,8 @@ def set_vocab(self):
2288
2293
chat_eos_token_id = token_id
2289
2294
token = token .encode ("utf-8" )
2290
2295
if toktypes [token_id ] != SentencePieceTokenTypes .UNUSED :
2291
- assert (tokens [token_id ] == token )
2296
+ if tokens [token_id ] != token :
2297
+ logger .warning (f'replacing token { token_id } : { tokens [token_id ].decode ("utf-8" )!r} -> { token .decode ("utf-8" )!r} ' )
2292
2298
tokens [token_id ] = token
2293
2299
scores [token_id ] = - 1000.0
2294
2300
toktypes [token_id ] = SentencePieceTokenTypes .USER_DEFINED
@@ -2474,6 +2480,7 @@ def set_vocab(self):
2474
2480
special_vocab ._set_special_token ("middle" , 68 )
2475
2481
special_vocab ._set_special_token ("fsep" , 70 )
2476
2482
special_vocab ._set_special_token ("eot" , 107 )
2483
+ special_vocab .chat_template = None # do not add it twice
2477
2484
special_vocab .add_to_gguf (self .gguf_writer )
2478
2485
2479
2486
self .gguf_writer .add_add_space_prefix (False )
@@ -3627,10 +3634,10 @@ def main() -> None:
3627
3634
logger .error ("Error: Cannot use temp file when splitting" )
3628
3635
sys .exit (1 )
3629
3636
3630
- fname_out = None
3631
-
3632
3637
if args .outfile is not None :
3633
3638
fname_out = args .outfile
3639
+ else :
3640
+ fname_out = dir_model
3634
3641
3635
3642
logger .info (f"Loading model: { dir_model .name } " )
3636
3643
@@ -3661,7 +3668,6 @@ def main() -> None:
3661
3668
else :
3662
3669
logger .info ("Exporting model..." )
3663
3670
model_instance .write ()
3664
- assert model_instance .fname_out is not None
3665
3671
out_path = f"{ model_instance .fname_out .parent } { os .sep } " if is_split else model_instance .fname_out
3666
3672
logger .info (f"Model successfully exported to { out_path } " )
3667
3673
0 commit comments