2025-02-02 14:58:18 -05:00
# SPDX-License-Identifier: Apache-2.0
2025-06-03 11:20:17 -07:00
# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
2025-02-02 14:58:18 -05:00
2023-11-30 19:43:13 -05:00
import pytest
2025-05-08 14:05:54 +08:00
from vllm . config import ModelConfig
2024-09-11 00:49:11 +08:00
from vllm . entrypoints . chat_utils import apply_hf_chat_template , load_chat_template
2024-01-17 05:33:14 +00:00
from vllm . entrypoints . openai . protocol import ChatCompletionRequest
2024-03-25 23:59:47 +09:00
from vllm . transformers_utils . tokenizer import get_tokenizer
2023-11-30 19:43:13 -05:00
2025-05-08 14:05:54 +08:00
from . . . models . registry import HF_EXAMPLE_MODELS
2024-09-18 09:56:58 -04:00
from . . . utils import VLLM_PATH
2024-08-07 17:12:05 +08:00
chatml_jinja_path = VLLM_PATH / " examples/template_chatml.jinja "
2024-01-14 12:37:58 -08:00
assert chatml_jinja_path . exists ( )
2023-11-30 19:43:13 -05:00
# Define models, templates, and their corresponding expected outputs
2025-06-12 10:57:10 +08:00
MODEL_TEMPLATE_GENERATION_OUTPUT = [
2024-09-29 20:59:47 +03:00
(
" facebook/opt-125m " ,
chatml_jinja_path ,
True ,
False ,
""" <|im_start|>user
2023-11-30 19:43:13 -05:00
Hello < | im_end | >
< | im_start | > assistant
Hi there ! < | im_end | >
< | im_start | > user
What is the capital of < | im_end | >
< | im_start | > assistant
""" ,
) ,
2024-09-29 20:59:47 +03:00
(
" facebook/opt-125m " ,
chatml_jinja_path ,
False ,
False ,
""" <|im_start|>user
2023-11-30 19:43:13 -05:00
Hello < | im_end | >
< | im_start | > assistant
Hi there ! < | im_end | >
< | im_start | > user
2024-09-29 20:59:47 +03:00
What is the capital of """ ,
) ,
(
" facebook/opt-125m " ,
chatml_jinja_path ,
False ,
True ,
""" <|im_start|>user
Hello < | im_end | >
< | im_start | > assistant
Hi there ! < | im_end | >
< | im_start | > user
What is the capital of < | im_end | >
< | im_start | > assistant
The capital of """ ,
) ,
2023-11-30 19:43:13 -05:00
]
TEST_MESSAGES = [
{ " role " : " user " , " content " : " Hello " } ,
{ " role " : " assistant " , " content " : " Hi there! " } ,
{ " role " : " user " , " content " : " What is the capital of " } ,
]
2024-09-29 20:59:47 +03:00
ASSISTANT_MESSAGE_TO_CONTINUE = { " role " : " assistant " , " content " : " The capital of " }
2023-11-30 19:43:13 -05:00
2024-05-09 13:48:33 +08:00
def test_load_chat_template ( ) :
2023-11-30 19:43:13 -05:00
# Testing chatml template
2024-07-18 00:13:30 -07:00
template_content = load_chat_template ( chat_template = chatml_jinja_path )
2023-11-30 19:43:13 -05:00
# Test assertions
assert template_content is not None
# Hard coded value for template_chatml.jinja
assert (
template_content
== """ { % f or message in messages % } {{ ' <|im_start|> ' + message[ ' role ' ] + ' \\ n ' + message[ ' content ' ]}} { % i f (loop.last and add_generation_prompt) or not loop.last % } {{ ' <|im_end|> ' + ' \\ n ' }} { % e ndif % } { % e ndfor % }
2025-10-06 06:12:40 +01:00
{ % if add_generation_prompt and messages [ - 1 ] [ ' role ' ] != ' assistant ' % } { { ' <|im_start|>assistant \\ n ' } } { % endif % } """ # noqa: E501
)
2023-11-30 19:43:13 -05:00
2024-05-09 13:48:33 +08:00
def test_no_load_chat_template_filelike ( ) :
2023-11-30 19:43:13 -05:00
# Testing chatml template
template = " ../../examples/does_not_exist "
2024-04-24 02:19:03 +08:00
with pytest . raises ( ValueError , match = " looks like a file path " ) :
2024-07-18 00:13:30 -07:00
load_chat_template ( chat_template = template )
2024-04-24 02:19:03 +08:00
2024-05-09 13:48:33 +08:00
def test_no_load_chat_template_literallike ( ) :
2024-04-24 02:19:03 +08:00
# Testing chatml template
template = " {{ messages }} "
2024-07-18 00:13:30 -07:00
template_content = load_chat_template ( chat_template = template )
2023-11-30 19:43:13 -05:00
2024-04-24 02:19:03 +08:00
assert template_content == template
2023-11-30 19:43:13 -05:00
@pytest.mark.parametrize (
2024-09-29 20:59:47 +03:00
" model,template,add_generation_prompt,continue_final_message,expected_output " ,
2025-06-12 10:57:10 +08:00
MODEL_TEMPLATE_GENERATION_OUTPUT ,
)
2024-05-09 13:48:33 +08:00
def test_get_gen_prompt (
model , template , add_generation_prompt , continue_final_message , expected_output
2024-09-29 20:59:47 +03:00
) :
2025-05-08 14:05:54 +08:00
model_info = HF_EXAMPLE_MODELS . find_hf_info ( model )
model_info . check_available_online ( on_fail = " skip " )
model_config = ModelConfig (
model ,
tokenizer = model_info . tokenizer or model ,
tokenizer_mode = model_info . tokenizer_mode ,
trust_remote_code = model_info . trust_remote_code ,
2025-07-28 10:42:40 +08:00
revision = model_info . revision ,
2025-05-08 14:05:54 +08:00
hf_overrides = model_info . hf_overrides ,
2025-09-04 08:22:41 +01:00
skip_tokenizer_init = model_info . skip_tokenizer_init ,
enforce_eager = model_info . enforce_eager ,
dtype = model_info . dtype ,
)
2025-05-08 14:05:54 +08:00
2023-11-30 19:43:13 -05:00
# Initialize the tokenizer
2025-05-08 14:05:54 +08:00
tokenizer = get_tokenizer (
tokenizer_name = model_config . tokenizer ,
trust_remote_code = model_config . trust_remote_code ,
)
2024-07-18 00:13:30 -07:00
template_content = load_chat_template ( chat_template = template )
2023-11-30 19:43:13 -05:00
# Create a mock request object using keyword arguments
mock_request = ChatCompletionRequest (
model = model ,
2024-09-29 20:59:47 +03:00
messages = TEST_MESSAGES + [ ASSISTANT_MESSAGE_TO_CONTINUE ]
if continue_final_message
else TEST_MESSAGES ,
add_generation_prompt = add_generation_prompt ,
continue_final_message = continue_final_message ,
)
2023-11-30 19:43:13 -05:00
# Call the function and get the result
2024-09-11 00:49:11 +08:00
result = apply_hf_chat_template (
2025-05-13 23:27:26 -07:00
tokenizer = tokenizer ,
2023-11-30 19:43:13 -05:00
conversation = mock_request . messages ,
2024-08-07 17:12:05 +08:00
chat_template = mock_request . chat_template or template_content ,
2025-05-13 23:27:26 -07:00
model_config = model_config ,
2025-03-24 21:50:09 +08:00
tools = None ,
2024-07-18 00:13:30 -07:00
add_generation_prompt = mock_request . add_generation_prompt ,
2024-09-29 20:59:47 +03:00
continue_final_message = mock_request . continue_final_message ,
2024-08-07 17:12:05 +08:00
)
2023-11-30 19:43:13 -05:00
# Test assertion
2024-03-10 19:49:14 -07:00
assert result == expected_output , (
f " The generated prompt does not match the expected output for "
f " model { model } and template { template } "
)