main
py 100 lines 3.51 KB
Raw
1 # SPDX-License-Identifier: Apache-2.0
2 # SPDX-FileCopyrightText: Copyright contributors to the vLLM project
3
4 import pytest
5 from transformers import AutoTokenizer, PreTrainedTokenizerBase
6
7 from vllm.entrypoints.generate.base.protocol import DeltaMessage
8 from vllm.entrypoints.openai.chat_completion.protocol import ChatCompletionRequest
9 from vllm.reasoning import ReasoningParserManager
10 from vllm.reasoning.deepseek_r1_reasoning_parser import DeepSeekR1ReasoningParser
11 from vllm.reasoning.deepseek_v3_reasoning_parser import DeepSeekV3ReasoningParser
12 from vllm.reasoning.identity_reasoning_parser import IdentityReasoningParser
13
14 pytestmark = pytest.mark.skip_global_cleanup
15
16 REASONING_MODEL_NAME = "deepseek-ai/DeepSeek-V3.1"
17
18
19 @pytest.fixture(scope="module")
20 def tokenizer() -> PreTrainedTokenizerBase:
21 return AutoTokenizer.from_pretrained(REASONING_MODEL_NAME)
22
23
24 @pytest.mark.parametrize(
25 "thinking,expected_parser_type",
26 [
27 (True, DeepSeekR1ReasoningParser),
28 (False, IdentityReasoningParser),
29 ],
30 )
31 def test_parser_selection(tokenizer, thinking, expected_parser_type):
32 parser = DeepSeekV3ReasoningParser(
33 tokenizer, chat_template_kwargs={"thinking": thinking}
34 )
35
36 assert isinstance(parser._parser, expected_parser_type)
37
38
39 def test_deepseek_v4_reasoning_parser_alias():
40 from vllm.reasoning.deepseek_v4_engine_reasoning_parser import (
41 DeepSeekV4ParserReasoningAdapter,
42 )
43
44 parser_cls = ReasoningParserManager.get_reasoning_parser("deepseek_v4")
45
46 assert parser_cls is DeepSeekV4ParserReasoningAdapter
47
48
49 def test_identity_reasoning_parser_basic(tokenizer):
50 parser = IdentityReasoningParser(tokenizer)
51
52 # Test is_reasoning_end always returns True
53 input_text = "This is some output"
54 input_tokens = tokenizer.tokenize(input_text)
55 input_ids = tokenizer.convert_tokens_to_ids(input_tokens)
56 assert parser.is_reasoning_end(input_ids) is True
57 assert parser.is_reasoning_end_streaming(input_ids, input_ids) is True
58
59 # Test extract_content_ids returns all input_ids
60 assert parser.extract_content_ids(input_ids) == input_ids
61
62 # Test extract_reasoning returns (None, model_output)
63 request = ChatCompletionRequest(model="test-model", messages=[], temperature=1.0)
64 reasoning, content = parser.extract_reasoning(input_text, request)
65 assert reasoning is None
66 assert content == input_text
67
68 # Test extract_reasoning_streaming returns DeltaMessage or None
69 result = parser.extract_reasoning_streaming(
70 previous_text="",
71 current_text="Hello world",
72 delta_text="Hello world",
73 previous_token_ids=[],
74 current_token_ids=input_ids,
75 delta_token_ids=input_ids,
76 )
77 assert isinstance(result, DeltaMessage)
78 assert result.content == "Hello world"
79
80 # If delta_text is empty, should return None
81 result_none = parser.extract_reasoning_streaming(
82 previous_text="Hello world",
83 current_text="Hello world",
84 delta_text="",
85 previous_token_ids=input_ids,
86 current_token_ids=input_ids,
87 delta_token_ids=[],
88 )
89 assert result_none is None
90
91
92 @pytest.mark.parametrize("thinking,expected", [(True, 3), (False, 0)])
93 def test_count_reasoning_tokens_delegates(tokenizer, thinking, expected):
94 parser = DeepSeekV3ReasoningParser(
95 tokenizer, chat_template_kwargs={"thinking": thinking}
96 )
97 think = tokenizer.convert_tokens_to_ids(["<think>", "</think>"])
98 token_ids = [think[0], 11, 12, 13, think[1], 14]
99
100 assert parser.count_reasoning_tokens(token_ids) == expected