main
py 66 lines 2.3 KB
Raw
1 # SPDX-License-Identifier: Apache-2.0
2 # SPDX-FileCopyrightText: Copyright contributors to the vLLM project
3
4 from collections.abc import Sequence
5
6 from vllm.entrypoints.generate.base.protocol import DeltaMessage
7 from vllm.reasoning.basic_parsers import BaseThinkingReasoningParser
8
9
10 class DeepSeekR1ReasoningParser(BaseThinkingReasoningParser):
11 """Reasoning parser for DeepSeek R1 model.
12
13 The DeepSeek R1 model uses <think>...</think> tokens to denote reasoning
14 text. This parser extracts the reasoning content from the model output.
15 """
16
17 @property
18 def start_token(self) -> str:
19 """The token that starts reasoning content."""
20 return "<think>"
21
22 @property
23 def end_token(self) -> str:
24 """The token that ends reasoning content."""
25 return "</think>"
26
27 def extract_reasoning_streaming(
28 self,
29 previous_text: str,
30 current_text: str,
31 delta_text: str,
32 previous_token_ids: Sequence[int],
33 current_token_ids: Sequence[int],
34 delta_token_ids: Sequence[int],
35 ) -> DeltaMessage | None:
36 ret = super().extract_reasoning_streaming(
37 previous_text,
38 current_text,
39 delta_text,
40 previous_token_ids,
41 current_token_ids,
42 delta_token_ids,
43 )
44 if (
45 ret is not None
46 and self.start_token_id not in previous_token_ids
47 and self.start_token_id not in delta_token_ids
48 ):
49 if self.end_token_id in delta_token_ids:
50 # end token in delta with more tokens,
51 # extract reasoning content and content
52 end_index = delta_text.find(self.end_token)
53 reasoning = delta_text[:end_index]
54 content = delta_text[end_index + len(self.end_token) :]
55 return DeltaMessage(
56 reasoning=reasoning,
57 content=content if content else None,
58 )
59 elif self.end_token_id in previous_token_ids:
60 # end token in previous, thinking content ends
61 return DeltaMessage(content=delta_text)
62 else:
63 # no end token in previous or delta, reasoning content continues
64 return DeltaMessage(reasoning=delta_text)
65
66 return ret