[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().