[Refactor] Remove unused interface methods (#57194)

Signed-off-by: sfeng33 <4florafeng@gmail.com>

Flora Feng committed Sep 16, 2026 at 17:00 UTC e0705731be04aac90838f318fcdae15c56a53080
5 files changed +19 -200
tests/entrypoints/openai/responses/test_parsable_context_unit.py
-9
@@ -36,9 +36,6 @@ class _NoOpParser(DelegatingParser):
36 def is_reasoning_end(self, input_ids: list[int]) -> bool:
37 return False
38
39 - def extract_content_ids(self, input_ids: list[int]) -> list[int]:
40 - return input_ids
41 -
39 def extract_reasoning(self, model_output, request):
40 return None, model_output
41
@@ -63,9 +60,6 @@ class _ReasoningOnlyParser(DelegatingParser):
60 def is_reasoning_end(self, input_ids: list[int]) -> bool:
61 return False
62
66 - def extract_content_ids(self, input_ids: list[int]) -> list[int]:
67 - return input_ids
68 -
63 def extract_reasoning(self, model_output, request):
64 if "<think>" in model_output and "</think>" in model_output:
65 start = model_output.index("<think>") + len("<think>")
@@ -131,9 +125,6 @@ class _ToolCallingParser(DelegatingParser):
125 def is_reasoning_end(self, input_ids: list[int]) -> bool:
126 return False
127
134 - def extract_content_ids(self, input_ids: list[int]) -> list[int]:
135 - return input_ids
136 -
128 def extract_reasoning(self, model_output, request):
129 return None, model_output
130
tests/entrypoints/openai/test_tool_choice_content_none.py
-3
@@ -31,9 +31,6 @@ class _DummyDelegatingParser(DelegatingParser):
31 def is_reasoning_end(self, input_ids: list[int]) -> bool:
32 return False
33
34 - def extract_content_ids(self, input_ids: list[int]) -> list[int]:
35 - return input_ids
36 -
34 def extract_reasoning(self, model_output: str, request):
35 return None, model_output
36
tests/entrypoints/unit_tests/test_context.py
+2 -2
@@ -71,8 +71,8 @@ async def generate_mock_outputs(
71 class FakeHarmonyParser(HarmonyParser):
72 def __init__(self):
73 # Skip HarmonyParser initialization and script outputs directly.
74 - self.reasoning_parser = None
75 - self.tool_parser = None
74 + self._reasoning_parser = None
75 + self._tool_parser = None
76 self._chunk_results: list[ChunkResult] = []
77 self._flush_results: list[list[Segment]] = []
78 self.processed_chunks: list[list[int]] = []
tests/tool_parsers/test_structural_tag_registry.py
+1 -1
@@ -623,7 +623,7 @@ def test_unified_parser_get_structural_tag_disables_reasoning(
623 tool_choice="auto",
624 )
625 parser = TestParser(MagicMock(), tools=sample_tools_strict)
626 - parser.reasoning_parser = MagicMock(adjust_request=lambda request: request)
626 + parser._reasoning_parser = MagicMock(adjust_request=lambda request: request)
627
628 parser.adjust_request(request)
629
vllm/parser/abstract_parser.py
+16 -185
@@ -6,7 +6,6 @@ import json
6 from abc import abstractmethod
7 from collections.abc import Sequence
8 from dataclasses import dataclass, field
9 -from functools import cached_property
9
10 from openai.types.responses import ToolChoiceFunction
11 from pydantic import TypeAdapter, ValidationError
@@ -84,23 +83,12 @@ class StreamState:
83
84
85 class Parser:
87 - """Abstract Parser class that unifies ReasoningParser and ToolParser into
88 - a single interface for parsing model output.
89 -
90 - This class provides a unified way to handle both reasoning extraction
91 - (e.g., chain-of-thought content in <think> tags) and tool call extraction
92 - (e.g., function calls in XML/JSON format) from model outputs.
93 -
94 - Subclasses can either:
95 - 1. Override the abstract methods directly for custom parsing logic
96 - 2. Set `reasoning_parser` and `tool_parser` properties to delegate to
97 - existing parser implementations
98 -
99 - Class Attributes:
100 - reasoning_parser_cls: The ReasoningParser class to use (for compatibility
101 - with code that needs the class, not instance).
102 - tool_parser_cls: The ToolParser class to use (for compatibility with
103 - code that needs the class, not instance).
86 + """Parse model output into reasoning, content and tool calls.
87 +
88 + The serving layer holds one ``Parser`` per request and calls only the
89 + members defined here. ``ParserEngine`` implements them over a single
90 + declarative engine; ``DelegatingParser`` composes a legacy
91 + ``ReasoningParser`` / ``ToolParser`` pair.
92 """
93
94 # Class-level parser classes for compatibility with existing patterns
@@ -150,29 +138,16 @@ class Parser:
138 engine_based=self._engine_based,
139 )
140
153 - @cached_property
154 - def vocab(self) -> dict[str, int]:
155 - """Get the vocabulary mapping from tokens to IDs."""
156 - return self.model_tokenizer.get_vocab()
157 -
141 @property
142 def reasoning_parser(self) -> ReasoningParser | None:
143 """The underlying reasoning parser, if any."""
144 return self._reasoning_parser
145
163 - @reasoning_parser.setter
164 - def reasoning_parser(self, parser: ReasoningParser | None) -> None:
165 - self._reasoning_parser = parser
166 -
146 @property
147 def tool_parser(self) -> ToolParser | None:
148 """The underlying tool parser, if any."""
149 return self._tool_parser
150
172 - @tool_parser.setter
173 - def tool_parser(self, parser: ToolParser | None) -> None:
174 - self._tool_parser = parser
175 -
151 def _initialize_history_tool_call_cnt(
152 self,
153 request: ChatCompletionRequest | ResponsesRequest,
@@ -186,119 +161,6 @@ class Parser:
161 state.history_tool_call_cnt = count_history_tool_calls(request)
162 state.history_tool_call_cnt_initialized = True
163
189 - # ========== Reasoning Parser Methods ==========
190 -
191 - @abstractmethod
192 - def is_reasoning_end(self, input_ids: list[int]) -> bool:
193 - """Check if the reasoning content ends in the input_ids.
194 -
195 - Used by structured engines like `xgrammar` to check if the
196 - reasoning content ends in the model output.
197 -
198 - Must be a pure function of the input_ids.
199 -
200 - Args:
201 - input_ids: The token IDs of the model output.
202 -
203 - Returns:
204 - True if the reasoning content ends in the input_ids.
205 -
206 - """
207 -
208 - def is_reasoning_end_streaming(
209 - self, input_ids: list[int], delta_ids: list[int]
210 - ) -> bool:
211 - """Check if the reasoning content ends during a decode step.
212 -
213 - Must be a pure function of the input_ids and delta_ids.
214 -
215 - Args:
216 - input_ids: The entire model output token IDs.
217 - delta_ids: The last few computed tokens at the current decode step.
218 -
219 - Returns:
220 - True if the reasoning content ends in the delta_ids.
221 -
222 - """
223 - return self.is_reasoning_end(input_ids)
224 -
225 - def find_reasoning_end_offset(self, token_ids: Sequence[int]) -> int | None:
226 - """Locate the token that ends reasoning within one window of tokens.
227 -
228 - Args:
229 - token_ids: The tokens to examine.
230 -
231 - Returns:
232 - The offset within ``token_ids`` of the last reasoning token, or
233 - ``len(token_ids)`` when reasoning does not end in this window. Parsers
234 - that cannot answer from a window alone always return ``None``; callers
235 - fall back to :meth:`is_reasoning_end_streaming`.
236 -
237 - """
238 - return None
239 -
240 - @abstractmethod
241 - def extract_content_ids(self, input_ids: list[int]) -> list[int]:
242 - """Extract content token IDs from the input_ids.
243 -
244 - This extracts the non-reasoning content (e.g., everything after
245 - the </think> tag).
246 -
247 - Args:
248 - input_ids: The token IDs of the model output.
249 -
250 - Returns:
251 - The extracted content token IDs.
252 -
253 - """
254 -
255 - @abstractmethod
256 - def extract_reasoning(
257 - self,
258 - model_output: str,
259 - request: ChatCompletionRequest | ResponsesRequest,
260 - ) -> tuple[str | None, str | None]:
261 - """Extract reasoning content from a complete model-generated string.
262 -
263 - Used for non-streaming responses where we have the entire model
264 - response available before sending to the client.
265 -
266 - Args:
267 - model_output: The complete model-generated string.
268 - request: The request object used to generate the output.
269 -
270 - Returns:
271 - A tuple of (reasoning, response_content).
272 -
273 - """
274 -
275 - @abstractmethod
276 - def extract_reasoning_streaming(
277 - self,
278 - previous_text: str,
279 - current_text: str,
280 - delta_text: str,
281 - previous_token_ids: Sequence[int],
282 - current_token_ids: Sequence[int],
283 - delta_token_ids: Sequence[int],
284 - ) -> DeltaMessage | None:
285 - """Extract reasoning content from a streaming delta message.
286 -
287 - Args:
288 - previous_text: Text from all previous tokens.
289 - current_text: Text including the current delta.
290 - delta_text: The new text in this delta.
291 - previous_token_ids: Token IDs from previous generation.
292 - current_token_ids: All token IDs including current.
293 - delta_token_ids: The new token IDs in this delta.
294 -
295 - Returns:
296 - A DeltaMessage with reasoning and/or content fields, or None.
297 -
298 - """
299 -
300 - # ========== Tool Parser Methods ==========
301 -
164 def adjust_request(
165 self, request: ChatCompletionRequest | ResponsesRequest
166 ) -> ChatCompletionRequest | ResponsesRequest:
@@ -317,48 +179,17 @@ class Parser:
179 return request
180
181 @abstractmethod
320 - def extract_tool_calls(
321 - self,
322 - model_output: str,
323 - request: ChatCompletionRequest | ResponsesRequest,
324 - ) -> ExtractedToolCallInformation:
325 - """Extract tool calls from a complete model-generated string.
182 + def is_reasoning_end(self, input_ids: list[int]) -> bool:
183 + """Check if the reasoning content ends in the input_ids.
184
327 - Used for non-streaming responses.
185 + Called with the rendered prompt to decide whether generation starts
186 + after reasoning. Must be a pure function of the input_ids.
187
188 Args:
330 - model_output: The complete model-generated string.
331 - request: The request object used to generate the output.
332 -
333 - Returns:
334 - ExtractedToolCallInformation containing the tool calls.
335 -
336 - """
337 -
338 - @abstractmethod
339 - def extract_tool_calls_streaming(
340 - self,
341 - previous_text: str,
342 - current_text: str,
343 - delta_text: str,
344 - previous_token_ids: Sequence[int],
345 - current_token_ids: Sequence[int],
346 - delta_token_ids: Sequence[int],
347 - request: ChatCompletionRequest | ResponsesRequest,
348 - ) -> DeltaMessage | None:
349 - """Extract tool calls from a streaming delta message.
350 -
351 - Args:
352 - previous_text: Text from all previous tokens.
353 - current_text: Text including the current delta.
354 - delta_text: The new text in this delta.
355 - previous_token_ids: Token IDs from previous generation.
356 - current_token_ids: All token IDs including current.
357 - delta_token_ids: The new token IDs in this delta.
358 - request: The request object.
189 + input_ids: The token IDs of the model output.
190
191 Returns:
361 - A DeltaMessage with tool_calls field, or None.
192 + True if the reasoning content ends in the input_ids.
193
194 """
195
@@ -764,14 +595,14 @@ class DelegatingParser(Parser):
595 return False
596 return self._reasoning_parser.is_reasoning_end(input_ids)
597
767 - def is_reasoning_end_streaming(
598 + def _is_reasoning_end_streaming(
599 self, input_ids: list[int], delta_ids: list[int]
600 ) -> bool:
601 if self._reasoning_parser is None:
602 return False
603 return self._reasoning_parser.is_reasoning_end_streaming(input_ids, delta_ids)
604
774 - def extract_content_ids(self, input_ids: list[int]) -> list[int]:
605 + def _extract_content_ids(self, input_ids: list[int]) -> list[int]:
606 if self._reasoning_parser is None:
607 return input_ids
608 return self._reasoning_parser.extract_content_ids(input_ids)
@@ -885,13 +716,13 @@ class DelegatingParser(Parser):
716 reasoning_parser.has_engine_confirmed_reasoning_end()
717 )
718 else:
888 - should_transition = self.is_reasoning_end_streaming(
719 + should_transition = self._is_reasoning_end_streaming(
720 current_token_ids, delta_token_ids
721 )
722 if should_transition:
723 state.reasoning_ended = True
724 reasoning_transitioned = True
894 - current_token_ids = self.extract_content_ids(delta_token_ids)
725 + current_token_ids = self._extract_content_ids(delta_token_ids)
726 # Flush whenever the reasoning parser is engine-based (not only
727 # when _engine_based is True): it buffers the post-marker text
728 # (e.g. the "<" of "<tool_call>"), surfaced via finish_streaming().