[perf] skip add_special_tokens=False kwarg on chat-template tokenize for slow tokenizers (#25953)
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.7
parent
acb8310183
commit
f829cafa3e
@@ -181,6 +181,18 @@ class OpenAIServingChat(OpenAIServingBase):
|
||||
# Per-request response parser for custom decoding (set by _encode_messages)
|
||||
self._response_parser: Optional[ResponseParserProtocol] = None
|
||||
|
||||
# Probe whether ``encode("")`` returns specials. If it does, we must
|
||||
# keep ``add_special_tokens=False`` at the chat-template encode site
|
||||
# to avoid double BOS; otherwise the kwarg is a no-op and dropping it
|
||||
# lets slow tokenizers (e.g. Kimi's TikTokenTokenizer) stay on the
|
||||
# fast internal path.
|
||||
try:
|
||||
self._tokenizer_auto_adds_specials = (
|
||||
len(self.tokenizer_manager.tokenizer.encode("")) > 0
|
||||
)
|
||||
except Exception:
|
||||
self._tokenizer_auto_adds_specials = True
|
||||
|
||||
def _handle_last_assistant_message(
|
||||
self,
|
||||
messages: List[Dict[str, Any]],
|
||||
@@ -729,15 +741,28 @@ class OpenAIServingChat(OpenAIServingBase):
|
||||
if request.chat_template_kwargs:
|
||||
extra_template_kwargs.update(request.chat_template_kwargs)
|
||||
|
||||
# Split apply_chat_template(tokenize=True) into render + encode so we
|
||||
# can skip add_special_tokens=False on tokenizers that don't auto-add
|
||||
# specials (Kimi-like, OpenAI-chat analogue of #25265). Chat
|
||||
# templates already include role/special tokens, so the encode must
|
||||
# avoid double BOS on tokenizers that would add it.
|
||||
encode_kwargs = (
|
||||
{"add_special_tokens": False}
|
||||
if self._tokenizer_auto_adds_specials
|
||||
else {}
|
||||
)
|
||||
try:
|
||||
prompt_ids = self.tokenizer_manager.tokenizer.apply_chat_template(
|
||||
rendered_prompt = self.tokenizer_manager.tokenizer.apply_chat_template(
|
||||
openai_compatible_messages,
|
||||
tokenize=True,
|
||||
tokenize=False,
|
||||
add_generation_prompt=True,
|
||||
tools=tools,
|
||||
return_dict=False,
|
||||
**extra_template_kwargs,
|
||||
)
|
||||
prompt_ids = self.tokenizer_manager.tokenizer.encode(
|
||||
rendered_prompt, **encode_kwargs
|
||||
)
|
||||
except Exception as e:
|
||||
# If the first attempt fails, try with flat function-only format.
|
||||
# Some templates (e.g. Mistral) expect tools without the OpenAI wrapper.
|
||||
@@ -747,13 +772,18 @@ class OpenAIServingChat(OpenAIServingBase):
|
||||
else None
|
||||
)
|
||||
try:
|
||||
prompt_ids = self.tokenizer_manager.tokenizer.apply_chat_template(
|
||||
openai_compatible_messages,
|
||||
tokenize=True,
|
||||
add_generation_prompt=True,
|
||||
tools=tools,
|
||||
return_dict=False,
|
||||
**extra_template_kwargs,
|
||||
rendered_prompt = (
|
||||
self.tokenizer_manager.tokenizer.apply_chat_template(
|
||||
openai_compatible_messages,
|
||||
tokenize=False,
|
||||
add_generation_prompt=True,
|
||||
tools=tools,
|
||||
return_dict=False,
|
||||
**extra_template_kwargs,
|
||||
)
|
||||
)
|
||||
prompt_ids = self.tokenizer_manager.tokenizer.encode(
|
||||
rendered_prompt, **encode_kwargs
|
||||
)
|
||||
except jinja2.TemplateError as template_error:
|
||||
# Template errors (e.g., from raise_exception in Jinja templates)
|
||||
|
||||
Reference in New Issue
Block a user