diff --git a/mlx_lm/server.py b/mlx_lm/server.py index ecfaa65..37b4165 100644 --- a/mlx_lm/server.py +++ b/mlx_lm/server.py @@ -524,6 +524,13 @@ class ResponseGenerator: if tokenizer.has_chat_template: process_message_content(messages) + if tools and not tokenizer.has_tool_calling: + logging.warning( + "Received tools but model does not support tool calling. " + "If you think this is an error, file an issue here: " + "https://github.com/ml-explore/mlx-lm/issues" + ) + return tokenizer.apply_chat_template( messages, tools=tools, diff --git a/mlx_lm/tokenizer_utils.py b/mlx_lm/tokenizer_utils.py index 2aa2e21..19fdae2 100644 --- a/mlx_lm/tokenizer_utils.py +++ b/mlx_lm/tokenizer_utils.py @@ -1,13 +1,12 @@ import importlib import json +import warnings from functools import partial from json import JSONDecodeError from typing import Any, Dict, List, Optional from transformers import AutoTokenizer, PreTrainedTokenizerFast -from .tool_parsers.json_tools import parse_tool_call as default_tool_parser - class StreamingDetokenizer: """The streaming detokenizer interface so that we can detokenize one token at a time. @@ -276,7 +275,7 @@ class TokenizerWrapper: self.has_chat_template = ( tokenizer.chat_template is not None or chat_template is not None ) - self._tool_parser = tool_parser or default_tool_parser + self._tool_parser = tool_parser self._tool_call_start = tool_call_start self._tool_call_end = tool_call_end @@ -290,11 +289,13 @@ class TokenizerWrapper: self._think_end_id = vocab[think_end] break - # Fallback to defaults if no tool call tokens are provided - if tool_call_start and tool_call_start not in vocab: - raise ValueError("Tool call start token not in vocab") - if tool_call_end and tool_call_end not in vocab: - raise ValueError("Tool call end token not in vocab") + # Disable tool calling if tool call tokens aren't in vocab + if (tool_call_start and tool_call_start not in vocab) or ( + tool_call_end and tool_call_end not in vocab + ): + self._tool_call_start = None + self._tool_call_end = None + self._tool_parser = None def apply_chat_template(self, *args, tokenize=True, **kwargs): if self._chat_template is not None: