Skip to content

Commit 1e8f425

Browse files
[Bugfix][Frontend] Raise exception when file-like chat template fails to be opened (#4292)
1 parent 2b7949c commit 1e8f425

File tree

2 files changed

+29
-13
lines changed

2 files changed

+29
-13
lines changed

tests/async_engine/test_chat_template.py

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -76,20 +76,29 @@ def test_load_chat_template():
7676
{% if add_generation_prompt and messages[-1]['role'] != 'assistant' %}{{ '<|im_start|>assistant\\n' }}{% endif %}""" # noqa: E501
7777

7878

79-
def test_no_load_chat_template():
79+
def test_no_load_chat_template_filelike():
8080
# Testing chatml template
8181
template = "../../examples/does_not_exist"
8282
tokenizer = MockTokenizer()
8383

84+
mock_serving_chat = MockServingChat(tokenizer)
85+
86+
with pytest.raises(ValueError, match="looks like a file path"):
87+
OpenAIServingChat._load_chat_template(mock_serving_chat,
88+
chat_template=template)
89+
90+
91+
def test_no_load_chat_template_literallike():
92+
# Testing chatml template
93+
template = "{{ messages }}"
94+
tokenizer = MockTokenizer()
95+
8496
mock_serving_chat = MockServingChat(tokenizer)
8597
OpenAIServingChat._load_chat_template(mock_serving_chat,
8698
chat_template=template)
8799
template_content = tokenizer.chat_template
88100

89-
# Test assertions
90-
assert template_content is not None
91-
# Hard coded value for template_chatml.jinja
92-
assert template_content == """../../examples/does_not_exist"""
101+
assert template_content == template
93102

94103

95104
@pytest.mark.asyncio

vllm/entrypoints/openai/serving_chat.py

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -319,23 +319,30 @@ async def chat_completion_full_generator(
319319
return response
320320

321321
def _load_chat_template(self, chat_template):
322+
tokenizer = self.tokenizer
323+
322324
if chat_template is not None:
323325
try:
324326
with open(chat_template, "r") as f:
325-
self.tokenizer.chat_template = f.read()
326-
except OSError:
327+
tokenizer.chat_template = f.read()
328+
except OSError as e:
329+
JINJA_CHARS = "{}\n"
330+
if not any(c in chat_template for c in JINJA_CHARS):
331+
msg = (f"The supplied chat template ({chat_template}) "
332+
f"looks like a file path, but it failed to be "
333+
f"opened. Reason: {e}")
334+
raise ValueError(msg) from e
335+
327336
# If opening a file fails, set chat template to be args to
328337
# ensure we decode so our escape are interpreted correctly
329-
self.tokenizer.chat_template = codecs.decode(
338+
tokenizer.chat_template = codecs.decode(
330339
chat_template, "unicode_escape")
331340

332341
logger.info(
333-
f"Using supplied chat template:\n{self.tokenizer.chat_template}"
334-
)
335-
elif self.tokenizer.chat_template is not None:
342+
f"Using supplied chat template:\n{tokenizer.chat_template}")
343+
elif tokenizer.chat_template is not None:
336344
logger.info(
337-
f"Using default chat template:\n{self.tokenizer.chat_template}"
338-
)
345+
f"Using default chat template:\n{tokenizer.chat_template}")
339346
else:
340347
logger.warning(
341348
"No chat template provided. Chat API will not work.")

0 commit comments

Comments
 (0)