Skip to content

Commit 0210024

Browse files
authored
[Bugfix] Pass effective chat template kwargs to reasoning parsers (vllm-project#40460)
Signed-off-by: Bugen Zhao <i@bugenzhao.com>
1 parent 4eafc72 commit 0210024

6 files changed

Lines changed: 71 additions & 17 deletions

File tree

vllm/entrypoints/openai/chat_completion/batch_serving.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -114,12 +114,15 @@ async def create_batch_chat_completion(
114114
"""
115115
tokenizer = self.renderer.tokenizer
116116
assert tokenizer is not None
117+
single_requests = [
118+
request.to_chat_completion_request(messages)
119+
for messages in request.messages
120+
]
117121

118122
reasoning_parser: ReasoningParser | None = None
119123
if self.reasoning_parser_cls:
120-
chat_template_kwargs = self._prepare_extra_chat_template_kwargs(
121-
request.chat_template_kwargs,
122-
self.default_chat_template_kwargs,
124+
chat_template_kwargs = self._effective_chat_template_kwargs(
125+
single_requests[0]
123126
)
124127
reasoning_parser = self.reasoning_parser_cls(
125128
tokenizer,
@@ -155,7 +158,7 @@ async def create_batch_chat_completion(
155158
self.default_sampling_params,
156159
self.override_max_tokens,
157160
)
158-
single_request = request.to_chat_completion_request(request.messages[i])
161+
single_request = single_requests[i]
159162
sampling_params = single_request.to_sampling_params(
160163
max_tokens, self.default_sampling_params
161164
)

vllm/entrypoints/openai/chat_completion/serving.py

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,18 @@ def warmup(self) -> None:
189189
)
190190
)
191191

192+
def _effective_chat_template_kwargs(
193+
self, request: ChatCompletionRequest
194+
) -> dict[str, Any]:
195+
return (
196+
request.build_chat_params(
197+
self.chat_template,
198+
self.chat_template_content_format,
199+
)
200+
.with_defaults(self.default_chat_template_kwargs)
201+
.chat_template_kwargs
202+
)
203+
192204
async def render_chat_request(
193205
self,
194206
request: ChatCompletionRequest,
@@ -231,10 +243,7 @@ async def create_chat_completion(
231243
# Streaming response
232244
tokenizer = self.renderer.tokenizer
233245
assert tokenizer is not None
234-
chat_template_kwargs = self._prepare_extra_chat_template_kwargs(
235-
request.chat_template_kwargs,
236-
self.default_chat_template_kwargs,
237-
)
246+
chat_template_kwargs = self._effective_chat_template_kwargs(request)
238247
reasoning_parser: ReasoningParser | None = None
239248
if self.reasoning_parser_cls:
240249
reasoning_parser = self.reasoning_parser_cls(

vllm/entrypoints/openai/parser/responses_parser.py

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# SPDX-License-Identifier: Apache-2.0
22
# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
33
import logging
4-
from collections.abc import Callable
4+
from typing import Any
55

66
from openai.types.responses import ResponseFunctionToolCall, ResponseOutputItem
77
from openai.types.responses.response_function_tool_call_output_item import (
@@ -15,6 +15,7 @@
1515
ResponseReasoningItem,
1616
)
1717

18+
from vllm.entrypoints.chat_utils import ChatTemplateContentFormatOption
1819
from vllm.entrypoints.constants import MCP_PREFIX
1920
from vllm.entrypoints.openai.responses.protocol import (
2021
ResponseInputOutputItem,
@@ -36,10 +37,12 @@ def __init__(
3637
self,
3738
*,
3839
tokenizer: TokenizerLike,
39-
reasoning_parser_cls: Callable[[TokenizerLike], ReasoningParser],
40+
reasoning_parser_cls: type[ReasoningParser],
4041
response_messages: list[ResponseInputOutputItem],
4142
request: ResponsesRequest,
4243
tool_parser_cls: type[ToolParser] | None,
44+
chat_template: str | None,
45+
chat_template_content_format: ChatTemplateContentFormatOption,
4346
):
4447
self.response_messages: list[ResponseInputOutputItem] = (
4548
# TODO: initial messages may not be properly typed
@@ -49,7 +52,14 @@ def __init__(
4952
self.tokenizer = tokenizer
5053
self.request = request
5154

52-
self.reasoning_parser_instance = reasoning_parser_cls(tokenizer)
55+
self.reasoning_parser_instance = reasoning_parser_cls(
56+
tokenizer,
57+
chat_template_kwargs=_effective_chat_template_kwargs(
58+
request,
59+
chat_template=chat_template,
60+
chat_template_content_format=chat_template_content_format,
61+
),
62+
)
5363
self.tool_parser_instance = None
5464
if tool_parser_cls is not None:
5565
self.tool_parser_instance = tool_parser_cls(tokenizer, request.tools)
@@ -159,10 +169,12 @@ def make_response_output_items_from_parsable_context(
159169
def get_responses_parser_for_simple_context(
160170
*,
161171
tokenizer: TokenizerLike,
162-
reasoning_parser_cls: Callable[[TokenizerLike], ReasoningParser],
172+
reasoning_parser_cls: type[ReasoningParser],
163173
response_messages: list[ResponseInputOutputItem],
164174
request: ResponsesRequest,
165175
tool_parser_cls,
176+
chat_template: str | None,
177+
chat_template_content_format: ChatTemplateContentFormatOption,
166178
) -> ResponsesParser:
167179
"""Factory function to create a ResponsesParser with
168180
optional reasoning parser.
@@ -176,4 +188,17 @@ def get_responses_parser_for_simple_context(
176188
response_messages=response_messages,
177189
request=request,
178190
tool_parser_cls=tool_parser_cls,
191+
chat_template=chat_template,
192+
chat_template_content_format=chat_template_content_format,
179193
)
194+
195+
196+
def _effective_chat_template_kwargs(
197+
request: ResponsesRequest,
198+
chat_template: str | None,
199+
chat_template_content_format: ChatTemplateContentFormatOption,
200+
) -> dict[str, Any]:
201+
return request.build_chat_params(
202+
default_template=chat_template,
203+
default_template_content_format=chat_template_content_format,
204+
).chat_template_kwargs

vllm/entrypoints/openai/responses/context.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
import json
77
import logging
88
from abc import ABC, abstractmethod
9-
from collections.abc import Callable
109
from contextlib import AsyncExitStack
1110
from dataclasses import replace
1211
from typing import TYPE_CHECKING, Any, Final, Union
@@ -273,7 +272,7 @@ def __init__(
273272
*,
274273
response_messages: list[ResponseInputOutputItem],
275274
tokenizer: TokenizerLike,
276-
reasoning_parser_cls: Callable[[TokenizerLike], ReasoningParser] | None,
275+
reasoning_parser_cls: type[ReasoningParser] | None,
277276
request: ResponsesRequest,
278277
available_tools: list[str] | None,
279278
tool_parser_cls: type[ToolParser] | None,
@@ -296,6 +295,8 @@ def __init__(
296295
response_messages=response_messages,
297296
request=request,
298297
tool_parser_cls=tool_parser_cls,
298+
chat_template=chat_template,
299+
chat_template_content_format=chat_template_content_format,
299300
)
300301
self.tool_parser_cls = tool_parser_cls
301302
self.request = request

vllm/entrypoints/openai/responses/serving.py

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,14 @@ def __init__(
267267

268268
self.tool_server = tool_server
269269

270+
def _effective_chat_template_kwargs(
271+
self, request: ResponsesRequest
272+
) -> dict[str, Any]:
273+
return request.build_chat_params(
274+
self.chat_template,
275+
self.chat_template_content_format,
276+
).chat_template_kwargs
277+
270278
def _validate_generator_input(
271279
self,
272280
engine_input: EngineInput,
@@ -464,7 +472,10 @@ async def create_responses(
464472
context = SimpleContext()
465473

466474
if self.parser and self.parser.reasoning_parser_cls is not None:
467-
reasoning_parser = self.parser.reasoning_parser_cls(tokenizer)
475+
reasoning_parser = self.parser.reasoning_parser_cls(
476+
tokenizer,
477+
chat_template_kwargs=self._effective_chat_template_kwargs(request),
478+
)
468479
if (
469480
isinstance(
470481
struct_out := sampling_params.structured_outputs,
@@ -835,7 +846,10 @@ async def responses_full_generator(
835846
and self.parser.reasoning_parser_cls is not None
836847
and isinstance(context, (SimpleContext, ParsableContext))
837848
):
838-
reasoning_parser = self.parser.reasoning_parser_cls(tokenizer)
849+
reasoning_parser = self.parser.reasoning_parser_cls(
850+
tokenizer,
851+
chat_template_kwargs=self._effective_chat_template_kwargs(request),
852+
)
839853
accumulated = getattr(context, "_accumulated_token_ids", []) or []
840854
num_reasoning_tokens = reasoning_parser.count_reasoning_tokens(accumulated)
841855

vllm/entrypoints/serve/render/serving.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -566,7 +566,9 @@ async def preprocess_chat(
566566
if reasoning_parser is not None:
567567
tokenizer = renderer.get_tokenizer()
568568
request = reasoning_parser(
569-
tokenizer, model_config=self.model_config
569+
tokenizer,
570+
model_config=self.model_config,
571+
chat_template_kwargs=chat_params.chat_template_kwargs,
570572
).adjust_request(request=request)
571573

572574
# tool parsing is done only if a tool_parser has been set and if

0 commit comments

Comments
 (0)