@tduncan / Nvidia-Optimization-Stack-VLLM Mirror · read-only / commits / 015069b017
Fork 0

A high-throughput and memory-efficient inference and serving engine for LLMs

Mirrored from https://github.com/tduncan-lum/Nvidia-Optimization-Stack---VLLM.git

Synced Nov 15, 12:15 UTC

[Misc] Optimize the Qwen3_ReasoningParser extract_reasoning_content (#17515)

Signed-off-by: chaunceyjiang <chaunceyjiang@gmail.com>

Chauncey committed May 1, 2025 at 18:29 UTC 015069b01741e9ecb9e604c7fe87fbdfc306ebe5
1 file changed +27 -26
vllm/reasoning/qwen3_reasoning_parser.py
+27 -26
@@ -1,6 +1,5 @@
1 # SPDX-License-Identifier: Apache-2.0
2
3 -import re
3 from collections.abc import Sequence
4 from typing import Optional, Union
5
@@ -31,9 +30,6 @@ class Qwen3ReasoningParser(ReasoningParser):
30 self.think_start_token = "<think>"
31 self.think_end_token = "</think>"
32
34 - self.reasoning_regex = re.compile(
35 - rf"{self.think_start_token}(.*?){self.think_end_token}", re.DOTALL)
36 -
33 if not self.model_tokenizer:
34 raise ValueError(
35 "The model tokenizer must be passed to the ReasoningParser "
@@ -121,29 +117,34 @@ class Qwen3ReasoningParser(ReasoningParser):
117 def extract_reasoning_content(
118 self, model_output: str, request: ChatCompletionRequest
119 ) -> tuple[Optional[str], Optional[str]]:
120 + """
121 + Extract reasoning content from the model output.
122 +
123 + For text <think>abc</think>xyz:
124 + - 'abc' goes to reasoning_content
125 + - 'xyz' goes to content
126
125 - # Check if the model output contains the <think> tokens.
127 + Returns:
128 + tuple[Optional[str], Optional[str]]: reasoning content and content
129 + """
130 +
131 + # Check if the model output contains the <think> and </think> tokens.
132 if (self.think_start_token not in model_output
133 or self.think_end_token not in model_output):
134 return None, model_output
129 - else:
130 - # Use a regex to find the reasoning content
131 - reasoning_content = self.reasoning_regex.findall(model_output)[0]
132 -
133 - # Remove the reasoning content from the model output
134 - # Although <think> token is always at the
135 - # beginning of the line, we cannot guarantee that the
136 - # other models will follow this convention.
137 - # Therefore, we need to add :start_index.
138 - start_index = model_output.find(self.think_start_token)
139 - if start_index != -1:
140 - end_index = start_index + len(
141 - f"{self.think_start_token}{reasoning_content}{self.think_end_token}"
142 - )
143 - model_output = model_output[:start_index] + \
144 - model_output[end_index:]
145 -
146 - if len(model_output) == 0:
147 - return reasoning_content, None
148 -
149 - return reasoning_content, model_output
135 + # Check if the <think> is present in the model output, remove it
136 + # if it is present.
137 + model_output_parts = model_output.partition(self.think_start_token)
138 + model_output = model_output_parts[2] if model_output_parts[
139 + 1] else model_output_parts[0]
140 + # Check if the model output contains the </think> tokens.
141 + # If the end token is not found, return the model output as is.
142 + if self.think_end_token not in model_output:
143 + return None, model_output
144 +
145 + # Extract reasoning content from the model output.
146 + reasoning_content, _, content = model_output.partition(
147 + self.think_end_token)
148 +
149 + final_content = content or None
150 + return reasoning_content, final_content