main
py 61 lines 2.28 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 from typing import TYPE_CHECKING
6
7 from vllm.entrypoints.generate.base.protocol import DeltaMessage
8 from vllm.parser.engine.registered_adapters import MinimaxM2ParserReasoningAdapter
9 from vllm.reasoning.abs_reasoning_parsers import ReasoningParser
10 from vllm.tokenizers import TokenizerLike
11
12 if TYPE_CHECKING:
13 from vllm.entrypoints.openai.chat_completion.protocol import ChatCompletionRequest
14 from vllm.entrypoints.openai.responses.protocol import ResponsesRequest
15
16
17 class MiniMaxM2ReasoningParser(MinimaxM2ParserReasoningAdapter): # type: ignore[valid-type, misc]
18 """Reasoning parser for MiniMax M2 model.
19
20 MiniMax M2 models don't generate <think> start token, only </think> end
21 token. All content before </think> is reasoning, content after is the
22 actual response.
23 """
24
25
26 class MiniMaxM2AppendThinkReasoningParser(ReasoningParser):
27 """Reasoning parser for MiniMax M2 model."""
28
29 def __init__(self, tokenizer: TokenizerLike, *args, **kwargs):
30 super().__init__(tokenizer, *args, **kwargs)
31 self.end_token_id = self.vocab.get("</think>")
32 self.start_token_id = self.vocab.get("<think>")
33
34 def is_reasoning_end(self, input_ids: Sequence[int]) -> bool:
35 end_token_id = self.end_token_id
36 start_token_id = self.start_token_id
37 for input_id in reversed(input_ids):
38 if input_id in (end_token_id, start_token_id):
39 return input_id == end_token_id
40 return False
41
42 def extract_content_ids(self, input_ids: list[int]) -> list[int]:
43 return input_ids
44
45 def extract_reasoning_streaming(
46 self,
47 previous_text: str,
48 current_text: str,
49 delta_text: str,
50 previous_token_ids: Sequence[int],
51 current_token_ids: Sequence[int],
52 delta_token_ids: Sequence[int],
53 ) -> DeltaMessage | None:
54 if len(previous_token_ids) == 0:
55 delta_text = "<think>" + delta_text
56 return DeltaMessage(content=delta_text)
57
58 def extract_reasoning(
59 self, model_output: str, request: "ChatCompletionRequest | ResponsesRequest"
60 ) -> tuple[str | None, str | None]:
61 return None, "<think>" + model_output