@tduncan / Nvidia-Optimization-Stack-VLLM Mirror · read-only / commits / 478b49ddec
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 2, 04:45 UTC

[Refactor] Remove dead code from parser infrastructure (#44279)

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

Flora Feng committed Jun 2, 2026 at 12:08 UTC 478b49ddec6685a4afe39c34fbe03d73d15a469b
5 files changed +35 -328
tests/parser/test_streaming.py
+6 -4
@@ -7,7 +7,7 @@ import pytest
7
8 from vllm.entrypoints.openai.chat_completion.protocol import ChatCompletionRequest
9 from vllm.entrypoints.openai.engine.protocol import DeltaMessage
10 -from vllm.parser.abstract_parser import _WrappedParser
10 +from vllm.parser.abstract_parser import DelegatingParser
11 from vllm.reasoning.basic_parsers import BaseThinkingReasoningParser
12 from vllm.tool_parsers.hermes_tool_parser import Hermes2ProToolParser
13
@@ -45,9 +45,11 @@ def request_obj():
45
46
47 def make_parser(tokenizer, reasoning=False, tool=False):
48 - _WrappedParser.reasoning_parser_cls = ThinkReasoningParser if reasoning else None
49 - _WrappedParser.tool_parser_cls = Hermes2ProToolParser if tool else None
50 - return _WrappedParser(tokenizer)
48 + class TestParser(DelegatingParser):
49 + reasoning_parser_cls = ThinkReasoningParser if reasoning else None
50 + tool_parser_cls = Hermes2ProToolParser if tool else None
51 +
52 + return TestParser(tokenizer)
53
54
55 def stream_text(parser, tokenizer, text, request, prompt_token_ids=None):
vllm/parser/__init__.py
-18
@@ -4,7 +4,6 @@
4 from vllm.parser.abstract_parser import (
5 DelegatingParser,
6 Parser,
7 - _WrappedParser,
7 )
8 from vllm.parser.parser_manager import ParserManager
9
@@ -12,21 +11,4 @@ __all__ = [
11 "Parser",
12 "DelegatingParser",
13 "ParserManager",
15 - "_WrappedParser",
14 ]
17 -
18 -_PARSERS_TO_REGISTER = {
19 - "minimax_m2": ( # name
20 - "minimax_m2_parser", # filename
21 - "MiniMaxM2Parser", # class_name
22 - ),
23 -}
24 -
25 -
26 -def register_lazy_parsers():
27 - for name, (file_name, class_name) in _PARSERS_TO_REGISTER.items():
28 - module_path = f"vllm.parser.{file_name}"
29 - ParserManager.register_lazy_module(name, module_path, class_name)
30 -
31 -
32 -register_lazy_parsers()
vllm/parser/abstract_parser.py
+15 -41
@@ -37,12 +37,11 @@ from vllm.entrypoints.openai.responses.protocol import ResponsesRequest
37 from vllm.logger import init_logger
38 from vllm.reasoning.abs_reasoning_parsers import ReasoningParser
39 from vllm.tokenizers import TokenizerLike
40 -from vllm.tool_parsers.abstract_tool_parser import ToolParser
40 +from vllm.tool_parsers.abstract_tool_parser import Tool, ToolParser
41 from vllm.tool_parsers.streaming import (
42 extract_named_tool_call_streaming,
43 extract_required_tool_call_streaming,
44 )
45 -from vllm.tool_parsers.utils import Tool
45 from vllm.utils import random_uuid
46 from vllm.utils.mistral import is_mistral_tool_parser
47
@@ -91,19 +90,25 @@ class Parser:
90 reasoning_parser_cls: type[ReasoningParser] | None = None
91 tool_parser_cls: type[ToolParser] | None = None
92
94 - def __init__(self, tokenizer: TokenizerLike, *args, **kwargs):
95 - """
96 - Initialize the Parser.
97 -
98 - Args:
99 - tokenizer: The tokenizer used by the model. This is required for
100 - token-based parsing operations.
101 - """
93 + def __init__(
94 + self,
95 + tokenizer: TokenizerLike,
96 + tools: list[Tool] | None = None,
97 + *args,
98 + **kwargs,
99 + ):
100 self.model_tokenizer = tokenizer
101 self._reasoning_parser: ReasoningParser | None = None
102 self._tool_parser: ToolParser | None = None
103 self._stream_state = StreamState()
104
105 + if self.__class__.reasoning_parser_cls is not None:
106 + self._reasoning_parser = self.__class__.reasoning_parser_cls(
107 + tokenizer, *args, **kwargs
108 + )
109 + if self.__class__.tool_parser_cls is not None:
110 + self._tool_parser = self.__class__.tool_parser_cls(tokenizer, tools)
111 +
112 @cached_property
113 def vocab(self) -> dict[str, int]:
114 """Get the vocabulary mapping from tokens to IDs."""
@@ -893,34 +898,3 @@ class DelegatingParser(Parser):
898 self._append_unstreamed_tool_args(delta_message)
899
900 return delta_message
896 -
897 -
898 -class _WrappedParser(DelegatingParser):
899 - """
900 - A DelegatingParser subclass that instantiates parsers from class attributes.
901 -
902 - This class is used to dynamically create a parser that wraps individual
903 - ReasoningParser and ToolParser classes. The class attributes
904 - `reasoning_parser_cls` and `tool_parser_cls` should be set before
905 - instantiation.
906 -
907 - Usage:
908 - _WrappedParser.reasoning_parser_cls = MyReasoningParser
909 - _WrappedParser.tool_parser_cls = MyToolParser
910 - parser = _WrappedParser(tokenizer)
911 - """
912 -
913 - reasoning_parser_cls: type[ReasoningParser] | None = None
914 - tool_parser_cls: type[ToolParser] | None = None
915 -
916 - def __init__(
917 - self, tokenizer: TokenizerLike, tools: list[Tool] | None = None, **kwargs
918 - ):
919 - super().__init__(tokenizer)
920 - # Instantiate the underlying parsers from class attributes
921 - if self.__class__.reasoning_parser_cls is not None:
922 - self._reasoning_parser = self.__class__.reasoning_parser_cls(
923 - tokenizer, **kwargs
924 - )
925 - if self.__class__.tool_parser_cls is not None:
926 - self._tool_parser = self.__class__.tool_parser_cls(tokenizer, tools)
vllm/parser/minimax_m2_parser.py deleted
-61
@@ -1,61 +0,0 @@
1 -# SPDX-License-Identifier: Apache-2.0
2 -# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
3 -
4 -"""
5 -MiniMax M2 Parser - A unified parser for MiniMax M2 models.
6 -
7 -This parser combines the existing MiniMaxM2ReasoningParser and
8 -MinimaxM2ToolParser into a single unified interface by delegating
9 -to those implementations.
10 -"""
11 -
12 -from vllm.logger import init_logger
13 -from vllm.parser.abstract_parser import DelegatingParser
14 -from vllm.reasoning.minimax_m2_reasoning_parser import MiniMaxM2ReasoningParser
15 -from vllm.tokenizers import TokenizerLike
16 -from vllm.tool_parsers.abstract_tool_parser import (
17 - Tool,
18 -)
19 -from vllm.tool_parsers.minimax_m2_tool_parser import MinimaxM2ToolParser
20 -
21 -logger = init_logger(__name__)
22 -
23 -
24 -class MiniMaxM2Parser(DelegatingParser):
25 - """
26 - Unified parser for MiniMax M2 models that handles both reasoning
27 - extraction and tool call parsing.
28 -
29 - This parser delegates to the existing implementations:
30 - - MiniMaxM2ReasoningParser for reasoning extraction
31 - - MinimaxM2ToolParser for tool call parsing
32 -
33 - MiniMax M2 models have two special behaviors:
34 - 1. Reasoning: They don't generate <think> start token, only </think> end
35 - token. All content before </think> is reasoning, content after is the
36 - actual response.
37 - 2. Tool Calls: They use <minimax:tool_call>...</minimax:tool_call> tags
38 - with <invoke name="...">...</invoke> and <parameter name="...">...</parameter>
39 - syntax.
40 - """
41 -
42 - # Class-level parser classes for compatibility
43 - reasoning_parser_cls = MiniMaxM2ReasoningParser
44 - tool_parser_cls = MinimaxM2ToolParser
45 -
46 - def __init__(
47 - self,
48 - tokenizer: TokenizerLike,
49 - tools: list[Tool] | None = None,
50 - *args,
51 - **kwargs,
52 - ):
53 - super().__init__(tokenizer, *args, **kwargs)
54 -
55 - # Initialize the underlying parsers
56 - self._reasoning_parser = MiniMaxM2ReasoningParser(tokenizer, *args, **kwargs)
57 - self._tool_parser = MinimaxM2ToolParser(tokenizer, tools)
58 -
59 - logger.debug(
60 - "vLLM Successfully initialized parser %s!", self.__class__.__name__
61 - )
vllm/parser/parser_manager.py
+14 -204
@@ -3,14 +3,9 @@
3
4 from __future__ import annotations
5
6 -import importlib
7 -import os
8 -from collections.abc import Callable
6 from typing import TYPE_CHECKING
7
8 from vllm.logger import init_logger
12 -from vllm.utils.collection_utils import is_list_of
13 -from vllm.utils.import_utils import import_from_path
9
10 if TYPE_CHECKING:
11 from vllm.parser.abstract_parser import Parser
@@ -22,170 +17,10 @@ logger = init_logger(__name__)
17
18 class ParserManager:
19 """
25 - Central registry for Parser implementations.
26 -
27 - Supports two registration modes:
28 - - Eager registration via `register_module`
29 - - Lazy registration via `register_lazy_module`
20 + Provides a unified Parser by composing individual reasoning and tool
21 + parsers from their respective registries.
22 """
23
32 - parsers: dict[str, type[Parser]] = {}
33 - lazy_parsers: dict[str, tuple[str, str]] = {} # name -> (module_path, class_name)
34 -
35 - @classmethod
36 - def get_parser_internal(cls, name: str) -> type[Parser]:
37 - """
38 - Retrieve a registered or lazily registered Parser class.
39 -
40 - Args:
41 - name: The registered name of the parser.
42 -
43 - Returns:
44 - The Parser class.
45 -
46 - Raises:
47 - KeyError: If no parser is found under the given name.
48 - """
49 - if name in cls.parsers:
50 - return cls.parsers[name]
51 -
52 - if name in cls.lazy_parsers:
53 - return cls._load_lazy_parser(name)
54 -
55 - registered = ", ".join(cls.list_registered())
56 - raise KeyError(f"Parser '{name}' not found. Available parsers: {registered}")
57 -
58 - @classmethod
59 - def _load_lazy_parser(cls, name: str) -> type[Parser]:
60 - """Import and register a lazily loaded parser."""
61 - from vllm.parser.abstract_parser import Parser
62 -
63 - module_path, class_name = cls.lazy_parsers[name]
64 - try:
65 - mod = importlib.import_module(module_path)
66 - parser_cls = getattr(mod, class_name)
67 - if not issubclass(parser_cls, Parser):
68 - raise TypeError(
69 - f"{class_name} in {module_path} is not a Parser subclass."
70 - )
71 - cls.parsers[name] = parser_cls # cache
72 - return parser_cls
73 - except Exception as e:
74 - logger.exception(
75 - "Failed to import lazy parser '%s' from %s: %s",
76 - name,
77 - module_path,
78 - e,
79 - )
80 - raise
81 -
82 - @classmethod
83 - def _register_module(
84 - cls,
85 - module: type[Parser],
86 - module_name: str | list[str] | None = None,
87 - force: bool = True,
88 - ) -> None:
89 - """Register a Parser class immediately."""
90 - from vllm.parser.abstract_parser import Parser
91 -
92 - if not issubclass(module, Parser):
93 - raise TypeError(
94 - f"module must be subclass of Parser, but got {type(module)}"
95 - )
96 -
97 - if module_name is None:
98 - module_names = [module.__name__]
99 - elif isinstance(module_name, str):
100 - module_names = [module_name]
101 - elif is_list_of(module_name, str):
102 - module_names = module_name
103 - else:
104 - raise TypeError("module_name must be str, list[str], or None.")
105 -
106 - for name in module_names:
107 - if not force and name in cls.parsers:
108 - existed = cls.parsers[name]
109 - raise KeyError(f"{name} is already registered at {existed.__module__}")
110 - cls.parsers[name] = module
111 -
112 - @classmethod
113 - def register_lazy_module(cls, name: str, module_path: str, class_name: str) -> None:
114 - """
115 - Register a lazy module mapping for delayed import.
116 -
117 - Example:
118 - ParserManager.register_lazy_module(
119 - name="minimax_m2",
120 - module_path="vllm.parser.minimax_m2_parser",
121 - class_name="MiniMaxM2Parser",
122 - )
123 - """
124 - cls.lazy_parsers[name] = (module_path, class_name)
125 -
126 - @classmethod
127 - def register_module(
128 - cls,
129 - name: str | list[str] | None = None,
130 - force: bool = True,
131 - module: type[Parser] | None = None,
132 - ) -> type[Parser] | Callable[[type[Parser]], type[Parser]]:
133 - """
134 - Register a Parser class.
135 -
136 - Can be used as a decorator or called directly.
137 -
138 - Usage:
139 - @ParserManager.register_module("my_parser")
140 - class MyParser(Parser):
141 - ...
142 -
143 - Or:
144 - ParserManager.register_module(module=MyParser)
145 - """
146 - if not isinstance(force, bool):
147 - raise TypeError(f"force must be a boolean, but got {type(force)}")
148 -
149 - # Immediate registration
150 - if module is not None:
151 - cls._register_module(module=module, module_name=name, force=force)
152 - return module
153 -
154 - # Decorator usage
155 - def _decorator(obj: type[Parser]) -> type[Parser]:
156 - module_path = obj.__module__
157 - class_name = obj.__name__
158 -
159 - if isinstance(name, str):
160 - names = [name]
161 - elif name is not None and is_list_of(name, str):
162 - names = name
163 - else:
164 - names = [class_name]
165 -
166 - for n in names:
167 - cls.lazy_parsers[n] = (module_path, class_name)
168 -
169 - return obj
170 -
171 - return _decorator
172 -
173 - @classmethod
174 - def list_registered(cls) -> list[str]:
175 - """Return names of all registered parsers."""
176 - return sorted(set(cls.parsers.keys()) | set(cls.lazy_parsers.keys()))
177 -
178 - @classmethod
179 - def import_parser(cls, plugin_path: str) -> None:
180 - """Import a user-defined parser from an arbitrary path."""
181 - module_name = os.path.splitext(os.path.basename(plugin_path))[0]
182 - try:
183 - import_from_path(module_name, plugin_path)
184 - except Exception:
185 - logger.exception(
186 - "Failed to load module '%s' from %s.", module_name, plugin_path
187 - )
188 -
24 @classmethod
25 def get_tool_parser(
26 cls,
@@ -246,12 +81,10 @@ class ParserManager:
81 model_name: str | None = None,
82 ) -> type[Parser] | None:
83 """
249 - Get a unified Parser that handles both reasoning and tool parsing.
84 + Get a Parser that handles both reasoning and tool parsing.
85
251 - This method checks if a unified Parser exists that can handle both
252 - reasoning extraction and tool call parsing. If no unified parser
253 - exists, it creates a DelegatingParser that wraps the individual
254 - reasoning and tool parsers.
86 + Composes individual reasoning and tool parsers into a single
87 + DelegatingParser subclass.
88
89 Args:
90 tool_parser_name: The name of the tool parser.
@@ -262,37 +95,9 @@ class ParserManager:
95 Returns:
96 A Parser class, or None if neither parser is specified.
97 """
265 - from vllm.parser.abstract_parser import _WrappedParser
266 -
98 if not tool_parser_name and not reasoning_parser_name:
99 return None
100
270 - # Strategy 1: If both names match, check for a unified parser with that name
271 - if tool_parser_name and tool_parser_name == reasoning_parser_name:
272 - try:
273 - parser = cls.get_parser_internal(tool_parser_name)
274 - logger.info(
275 - "Using unified parser '%s' for both reasoning and tool parsing.",
276 - tool_parser_name,
277 - )
278 - return parser
279 - except KeyError:
280 - pass # No unified parser with this name
281 -
282 - # Strategy 2: Check for parser with either name
283 - for name in [tool_parser_name, reasoning_parser_name]:
284 - if name:
285 - try:
286 - parser = cls.get_parser_internal(name)
287 - logger.info(
288 - "Using unified parser '%s' for reasoning and tool parsing.",
289 - name,
290 - )
291 - return parser
292 - except KeyError:
293 - pass
294 -
295 - # Strategy 3: Create a DelegatingParser with the individual parser classes
101 reasoning_parser_cls = cls.get_reasoning_parser(reasoning_parser_name)
102 tool_parser_cls = cls.get_tool_parser(
103 tool_parser_name, enable_auto_tools, model_name
@@ -301,8 +106,13 @@ class ParserManager:
106 if reasoning_parser_cls is None and tool_parser_cls is None:
107 return None
108
304 - # Set the class-level attributes on the imported _WrappedParser
305 - _WrappedParser.reasoning_parser_cls = reasoning_parser_cls
306 - _WrappedParser.tool_parser_cls = tool_parser_cls
109 + from vllm.parser.abstract_parser import DelegatingParser
110 +
111 + r_cls = reasoning_parser_cls
112 + t_cls = tool_parser_cls
113 +
114 + class _Parser(DelegatingParser):
115 + reasoning_parser_cls = r_cls
116 + tool_parser_cls = t_cls
117
308 - return _WrappedParser
118 + return _Parser