1+ import importlib
12import json
23from functools import partial
34from json import JSONDecodeError
@@ -248,7 +249,11 @@ class TokenizerWrapper:
248249 """
249250
250251 def __init__ (
251- self , tokenizer , detokenizer_class = NaiveStreamingDetokenizer , eos_token_ids = None
252+ self ,
253+ tokenizer ,
254+ detokenizer_class = NaiveStreamingDetokenizer ,
255+ eos_token_ids = None ,
256+ chat_template = None ,
252257 ):
253258 self ._tokenizer = tokenizer
254259 self ._detokenizer_class = detokenizer_class
@@ -261,6 +266,10 @@ def __init__(
261266 self ._think_end = None
262267 self ._tool_call_start = None
263268 self ._tool_call_end = None
269+ self ._chat_template = chat_template
270+ self .has_chat_template = (
271+ tokenizer .chat_template is not None or chat_template is not None
272+ )
264273
265274 THINK_TOKENS = [("<think>" , "</think>" )]
266275 TOOL_CALL_TOKENS = [("<tool_call>" , "</tool_call>" )]
@@ -278,9 +287,15 @@ def __init__(
278287 self ._tool_call_end = tool_call_end
279288 break
280289
281- def apply_chat_template (self , * args , ** kwargs ):
290+ def apply_chat_template (self , * args , tokenize = True , ** kwargs ):
291+ if self ._chat_template is not None :
292+ out = self ._chat_template (* args , ** kwargs )
293+ if tokenize :
294+ out = self ._tokenizer .encode (out , add_special_tokens = False )
295+ return out
296+
282297 kwargs ["return_dict" ] = False
283- return self ._tokenizer .apply_chat_template (* args , ** kwargs )
298+ return self ._tokenizer .apply_chat_template (* args , tokenize = tokenize , ** kwargs )
284299
285300 def add_eos_token (self , token : str ):
286301 token_id = None
@@ -450,12 +465,28 @@ def load(
450465 if isinstance (eos_token_ids , int ):
451466 eos_token_ids = [eos_token_ids ]
452467
468+ tokenizer_config_file = model_path / "tokenizer_config.json"
469+ custom_tokenizer = None
470+ if tokenizer_config_file .exists ():
471+ with open (tokenizer_config_file , "r" , encoding = "utf-8" ) as fid :
472+ try :
473+ tokenizer_config = json .load (fid )
474+ except JSONDecodeError as e :
475+ raise JSONDecodeError (
476+ "Failed to parse tokenizer_config.json" , e .doc , e .pos
477+ )
478+ if tokenizer_type := tokenizer_config .get ("tokenizer_type" , False ):
479+ custom_tokenizer = importlib .import_module (
480+ f"mlx_lm.tokenizers.{ tokenizer_type } "
481+ )
482+
453483 if return_tokenizer :
454484 kwargs = tokenizer_config_extra or {}
455485 return TokenizerWrapper (
456486 AutoTokenizer .from_pretrained (model_path , ** kwargs ),
457487 detokenizer_class ,
458488 eos_token_ids = eos_token_ids ,
489+ chat_template = getattr (custom_tokenizer , "apply_chat_template" , None ),
459490 )
460491 else :
461492 return detokenizer_class
0 commit comments