main
py 36 lines 1.54 KB
Raw
1 # SPDX-License-Identifier: Apache-2.0
2 # SPDX-FileCopyrightText: Copyright contributors to the vLLM project
3
4 from openai.types.responses import ToolChoiceFunction
5
6 from vllm.entrypoints.openai.chat_completion.protocol import (
7 ChatCompletionNamedToolChoiceParam,
8 ChatCompletionRequest,
9 )
10 from vllm.entrypoints.openai.responses.protocol import ResponsesRequest
11 from vllm.parser.engine.registered_adapters import Gemma4ParserToolAdapter
12
13
14 class Gemma4EngineToolParser(Gemma4ParserToolAdapter): # type: ignore[valid-type, misc]
15 supports_required_and_named = False
16
17 def adjust_request(
18 self, request: ChatCompletionRequest | ResponsesRequest
19 ) -> ChatCompletionRequest | ResponsesRequest:
20 """Skip structured-output JSON for required/named tool choice.
21
22 Gemma4 emits its native ``<|tool_call>call:...`` syntax, which the
23 parser extracts directly. The base ``ToolParser.adjust_request`` would
24 set ``structured_outputs`` for required/named and force JSON via guided
25 decoding, conflicting with that native syntax (it leaks as content and
26 crashes EngineCore under speculative decoding). Skip it so the model
27 emits its native format (mirrors the GLM4 parser).
28 """
29 if request.tools:
30 tc = request.tool_choice
31 if tc == "required" or isinstance(
32 tc, (ChatCompletionNamedToolChoiceParam, ToolChoiceFunction)
33 ):
34 request.skip_special_tokens = False
35 return request
36 return super().adjust_request(request)