Skip to content

Commit a933921

Browse files
committed
style: fix pre-commit lint — ruff formatting and mypy type errors
- ruff: reformat long lines in tests and serving.py - mypy: annotate base_tag as dict[str, Any] in gptoss_reasoning_parser to allow nested dict indexing through copy.deepcopy result - mypy: suppress arg-type on list(name) in abs_reasoning_parsers where TypeIs narrowing is not respected under --python-version 3.10 Signed-off-by: Will Deines <will@garr.io>
1 parent d2ecd4a commit a933921

6 files changed

Lines changed: 45 additions & 105 deletions

File tree

tests/entrypoints/openai/parser/test_harmony_utils.py

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -944,9 +944,7 @@ def test_none_instructions_creates_section(self):
944944
assert '{"type":"object"}' in result
945945

946946
def test_custom_format_name(self):
947-
result = inject_response_formats(
948-
None, {"type": "object"}, format_name="order"
949-
)
947+
result = inject_response_formats(None, {"type": "object"}, format_name="order")
950948
assert "## order" in result
951949

952950
def test_compact_json_no_spaces(self):
@@ -955,15 +953,8 @@ def test_compact_json_no_spaces(self):
955953
"properties": {"name": {"type": "string"}},
956954
}
957955
result = inject_response_formats(None, schema)
958-
assert (
959-
'{"type":"object","properties":{"name":{"type":"string"}}}'
960-
in result
961-
)
956+
assert '{"type":"object","properties":{"name":{"type":"string"}}}' in result
962957

963958
def test_section_separated_by_blank_lines(self):
964-
result = inject_response_formats(
965-
"Instructions here.", {"type": "object"}
966-
)
967-
assert (
968-
"\n\n# Response Formats\n\n## structured_output\n\n" in result
969-
)
959+
result = inject_response_formats("Instructions here.", {"type": "object"})
960+
assert "\n\n# Response Formats\n\n## structured_output\n\n" in result

tests/entrypoints/openai/responses/test_structured_output.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -141,9 +141,7 @@ def test_choice(self):
141141

142142
def test_structural_tag_only_returns_none(self):
143143
"""structural_tag is not a content constraint -- should return None."""
144-
params = StructuredOutputsParams(
145-
structural_tag='{"type": "structural_tag"}'
146-
)
144+
params = StructuredOutputsParams(structural_tag='{"type": "structural_tag"}')
147145
result = _constraint_to_content_format(params)
148146

149147
assert result is None

tests/reasoning/test_gptoss_reasoning_parser.py

Lines changed: 11 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
from_function_tool_to_tag,
1616
no_func_reasoning_tag,
1717
tag_with_builtin_funcs,
18-
tag_with_function_tools,
1918
)
2019

2120
REASONING_MODEL_NAME = "openai/gpt-oss-120b"
@@ -410,10 +409,7 @@ def test_prepare_structured_tag_with_json_schema(self, reasoning_parser):
410409
assert len(parsed["format"]["tags"]) == 2
411410

412411
# Verify analysis tag is unchanged
413-
assert (
414-
parsed["format"]["tags"][0]["begin"]
415-
== "<|channel|>analysis<|message|>"
416-
)
412+
assert parsed["format"]["tags"][0]["begin"] == "<|channel|>analysis<|message|>"
417413
assert parsed["format"]["tags"][0]["content"]["type"] == "any_text"
418414

419415
# Verify final channel tag has the json_schema content constraint
@@ -531,21 +527,13 @@ def test_tool_choice_required_with_function_tools(self, reasoning_parser):
531527

532528
tag_begins = [t["begin"] for t in parsed["format"]["tags"]]
533529
# Function tool tags present
534-
assert (
535-
"<|channel|>commentary to=functions.get_weather<|message|>"
536-
in tag_begins
537-
)
538-
assert (
539-
"<|channel|>analysis to=functions.get_weather<|message|>"
540-
in tag_begins
541-
)
530+
assert "<|channel|>commentary to=functions.get_weather<|message|>" in tag_begins
531+
assert "<|channel|>analysis to=functions.get_weather<|message|>" in tag_begins
542532
# No final
543533
assert not any("final" in b for b in tag_begins)
544534
assert "<|channel|>final" not in parsed["format"]["triggers"]
545535

546-
def test_tool_choice_required_ignores_final_content_format(
547-
self, reasoning_parser
548-
):
536+
def test_tool_choice_required_ignores_final_content_format(self, reasoning_parser):
549537
"""Final is blocked even when final_content_format is provided."""
550538
content_fmt = {
551539
"type": "json_schema",
@@ -564,9 +552,7 @@ def test_tool_choice_required_ignores_final_content_format(
564552
tag_begins = [t["begin"] for t in parsed["format"]["tags"]]
565553
assert not any("final" in b for b in tag_begins)
566554

567-
def test_tool_choice_auto_with_tools_and_content_format(
568-
self, reasoning_parser
569-
):
555+
def test_tool_choice_auto_with_tools_and_content_format(self, reasoning_parser):
570556
"""Tool tags + final with content constraint for auto."""
571557
schema = {"type": "object", "properties": {"x": {"type": "integer"}}}
572558
content_fmt = {"type": "json_schema", "json_schema": schema}
@@ -583,10 +569,7 @@ def test_tool_choice_auto_with_tools_and_content_format(
583569

584570
tag_begins = [t["begin"] for t in parsed["format"]["tags"]]
585571
# Function tool tags
586-
assert (
587-
"<|channel|>commentary to=functions.compute<|message|>"
588-
in tag_begins
589-
)
572+
assert "<|channel|>commentary to=functions.compute<|message|>" in tag_begins
590573
# Final tag with content constraint
591574
assert "<|channel|>final<|message|>" in tag_begins
592575
assert "<|channel|>final" in parsed["format"]["triggers"]
@@ -598,9 +581,7 @@ def test_tool_choice_auto_with_tools_and_content_format(
598581
)
599582
assert final_tag["content"] == content_fmt
600583

601-
def test_tool_choice_auto_with_tools_final_is_any_text(
602-
self, reasoning_parser
603-
):
584+
def test_tool_choice_auto_with_tools_final_is_any_text(self, reasoning_parser):
604585
"""auto + function tools but no content format -> final allows free text."""
605586
fn_tools = [{"name": "get_weather", "parameters": {"type": "object"}}]
606587
result = reasoning_parser.prepare_structured_tag(
@@ -655,14 +636,8 @@ def test_mixed_builtin_and_function_tools(
655636
assert "<|channel|>commentary to=browser" in tag_begins
656637
assert "<|channel|>analysis to=browser" in tag_begins
657638
# Function tool tags
658-
assert (
659-
"<|channel|>commentary to=functions.get_weather<|message|>"
660-
in tag_begins
661-
)
662-
assert (
663-
"<|channel|>analysis to=functions.get_weather<|message|>"
664-
in tag_begins
665-
)
639+
assert "<|channel|>commentary to=functions.get_weather<|message|>" in tag_begins
640+
assert "<|channel|>analysis to=functions.get_weather<|message|>" in tag_begins
666641
# Final tag (auto + function tools)
667642
assert "<|channel|>final<|message|>" in tag_begins
668643
# General commentary trigger covers both builtin and function
@@ -684,14 +659,8 @@ def test_named_tool_choice(self, reasoning_parser):
684659

685660
tag_begins = [t["begin"] for t in parsed["format"]["tags"]]
686661
# Only get_weather tags, not get_stock
687-
assert (
688-
"<|channel|>commentary to=functions.get_weather<|message|>"
689-
in tag_begins
690-
)
691-
assert (
692-
"<|channel|>analysis to=functions.get_weather<|message|>"
693-
in tag_begins
694-
)
662+
assert "<|channel|>commentary to=functions.get_weather<|message|>" in tag_begins
663+
assert "<|channel|>analysis to=functions.get_weather<|message|>" in tag_begins
695664
assert not any("get_stock" in b for b in tag_begins)
696665
# No final (named tool choice blocks final)
697666
assert not any("final" in b for b in tag_begins)

vllm/entrypoints/openai/responses/serving.py

Lines changed: 13 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -168,9 +168,7 @@ def _constraint_to_content_format(
168168
if params.choice is not None:
169169
return {
170170
"type": "or",
171-
"elements": [
172-
{"type": "const_string", "value": c} for c in params.choice
173-
],
171+
"elements": [{"type": "const_string", "value": c} for c in params.choice],
174172
}
175173
return None
176174

@@ -526,11 +524,7 @@ async def create_responses(
526524
ft = [
527525
{
528526
"name": t.name,
529-
**(
530-
{"parameters": t.parameters}
531-
if t.parameters
532-
else {}
533-
),
527+
**({"parameters": t.parameters} if t.parameters else {}),
534528
}
535529
for t in request.tools
536530
if getattr(t, "type", None) == "function"
@@ -561,18 +555,14 @@ async def create_responses(
561555
# Content constraint present (json, regex,
562556
# grammar, choice, json_object). Embed it in the
563557
# final channel tag within the structural tag.
564-
content_fmt = _constraint_to_content_format(
565-
struct_out
566-
)
558+
content_fmt = _constraint_to_content_format(struct_out)
567559
if content_fmt is not None:
568-
structural_tag = (
569-
reasoning_parser.prepare_structured_tag(
570-
None,
571-
self.tool_server,
572-
final_content_format=content_fmt,
573-
tool_choice=request.tool_choice,
574-
function_tools=function_tools_for_parser,
575-
)
560+
structural_tag = reasoning_parser.prepare_structured_tag(
561+
None,
562+
self.tool_server,
563+
final_content_format=content_fmt,
564+
tool_choice=request.tool_choice,
565+
function_tools=function_tools_for_parser,
576566
)
577567
if structural_tag is not None:
578568
# Clear content constraints, set
@@ -597,10 +587,8 @@ async def create_responses(
597587
function_tools=function_tools_for_parser,
598588
)
599589
if tag is not None:
600-
sampling_params.structured_outputs = (
601-
StructuredOutputsParams(
602-
structural_tag=tag # type: ignore[call-arg]
603-
)
590+
sampling_params.structured_outputs = StructuredOutputsParams(
591+
structural_tag=tag # type: ignore[call-arg]
604592
)
605593
generator = self._generate_with_builtin_tools(
606594
request_id=request.request_id,
@@ -1256,9 +1244,7 @@ def _construct_input_messages_with_harmony(
12561244
# structural tag grammar already blocks tool channels, but
12571245
# omitting tools from the system/developer messages
12581246
# prevents the model from even reasoning about calling them.
1259-
tools_visible = (
1260-
with_custom_tools and request.tool_choice != "none"
1261-
)
1247+
tools_visible = with_custom_tools and request.tool_choice != "none"
12621248

12631249
sys_msg = self._construct_harmony_system_input_message(
12641250
request, tools_visible, tool_types
@@ -1269,9 +1255,7 @@ def _construct_input_messages_with_harmony(
12691255
# Per Harmony cookbook: developer message holds instructions,
12701256
# function tools, AND response format schemas.
12711257
response_format_schema = _extract_response_format_schema(request)
1272-
needs_dev_msg = (
1273-
tools_visible or response_format_schema is not None
1274-
)
1258+
needs_dev_msg = tools_visible or response_format_schema is not None
12751259

12761260
if needs_dev_msg:
12771261
dev_instructions = request.instructions

vllm/reasoning/abs_reasoning_parsers.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -312,7 +312,8 @@ def _decorator(obj: type[ReasoningParser]) -> type[ReasoningParser]:
312312
if isinstance(name, str):
313313
names = [name]
314314
elif is_list_of(name, str):
315-
names = name
315+
assert name is not None
316+
names = list(name)
316317
else:
317318
names = [class_name]
318319

vllm/reasoning/gptoss_reasoning_parser.py

Lines changed: 14 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import copy
44
import json
55
from collections.abc import Sequence
6-
from typing import TYPE_CHECKING
6+
from typing import TYPE_CHECKING, Any
77

88
from transformers import PreTrainedTokenizerBase
99

@@ -81,17 +81,13 @@ def from_function_tool_to_tag(name: str, parameters: dict | None) -> list[dict]:
8181
]
8282

8383

84-
def tag_with_function_tools(
85-
base_tag: dict, function_tools: list[dict]
86-
) -> dict:
84+
def tag_with_function_tools(base_tag: dict, function_tools: list[dict]) -> dict:
8785
new_tag = copy.deepcopy(base_tag)
8886

8987
# Add commentary trigger for function tools if not already covered
9088
# by the general commentary trigger (added by builtin tools).
9189
if "<|channel|>commentary to=" not in new_tag["format"]["triggers"]:
92-
new_tag["format"]["triggers"].append(
93-
"<|channel|>commentary to=functions."
94-
)
90+
new_tag["format"]["triggers"].append("<|channel|>commentary to=functions.")
9591

9692
for tool in function_tools:
9793
new_tag["format"]["tags"].extend(
@@ -207,7 +203,7 @@ def prepare_structured_tag(
207203
# There is potential risk for appending the tag to the original tag
208204
return original_tag
209205

210-
base_tag = copy.deepcopy(no_func_reasoning_tag)
206+
base_tag: dict[str, Any] = copy.deepcopy(no_func_reasoning_tag)
211207

212208
# Add builtin tool tags (unless tool_choice is "none")
213209
if tool_choice != "none" and tool_server is not None:
@@ -236,9 +232,7 @@ def prepare_structured_tag(
236232
t for t in function_tools if t["name"] == named
237233
]
238234
if effective_function_tools:
239-
base_tag = tag_with_function_tools(
240-
base_tag, effective_function_tools
241-
)
235+
base_tag = tag_with_function_tools(base_tag, effective_function_tools)
242236

243237
# Add final channel tag unless tool_choice blocks it
244238
if tool_choice != "required" and not isinstance(tool_choice, dict):
@@ -249,11 +243,13 @@ def prepare_structured_tag(
249243
if final_content_format
250244
else {"type": "any_text"}
251245
)
252-
base_tag["format"]["tags"].append({
253-
"begin": "<|channel|>final<|message|>",
254-
"content": final_content,
255-
"end": "<|end|>",
256-
})
246+
base_tag["format"]["tags"].append(
247+
{
248+
"begin": "<|channel|>final<|message|>",
249+
"content": final_content,
250+
"end": "<|end|>",
251+
}
252+
)
257253
base_tag["format"]["triggers"].append("<|channel|>final")
258254

259255
# For tool_choice=required or named tool, force at least one triggered
@@ -267,7 +263,8 @@ def prepare_structured_tag(
267263
# satisfying at_least_one with a pure reasoning channel instead of
268264
# an actual tool call.
269265
base_tag["format"]["tags"] = [
270-
t for t in base_tag["format"]["tags"]
266+
t
267+
for t in base_tag["format"]["tags"]
271268
if t.get("begin") != "<|channel|>analysis<|message|>"
272269
]
273270
base_tag["format"]["at_least_one"] = True

0 commit comments

Comments
 (0)