@tduncan / Nvidia-Optimization-Stack-VLLM Mirror · read-only / commits / b6af24fba7
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 14, 05:30 UTC

[CI][Entrypoints]: add filter to generation to filter out invalid tool calls (#22826)

Signed-off-by: Will Eaton <weaton@redhat.com>

Will Eaton committed Aug 13, 2025 at 23:09 UTC b6af24fba73cad27254e8826bbd842810cce7ee8
1 file changed +32 -16
tests/entrypoints/openai/test_openai_schema.py
+32 -16
@@ -54,38 +54,54 @@ def before_generate_case(context: schemathesis.hooks.HookContext, strategy):
54 op = context.operation
55 assert op is not None
56
57 - def no_file_type(case: schemathesis.models.Case):
57 + def no_invalid_types(case: schemathesis.models.Case):
58 """
59 - This filter skips test cases for the `POST /tokenize` endpoint where the
60 - HTTP request body uses `"type": "file"` in any message's content.
61 - We expect these cases to fail because that type isn't implemented here
62 - https://github.com/vllm-project/vllm/blob/0b34593017953051b3225b1483ce0f4670e3eb0e/vllm/entrypoints/chat_utils.py#L1038-L1095
59 + This filter skips test cases with invalid data that schemathesis
60 + incorrectly generates due to permissive schema configurations.
61 +
62 + 1. Skips `POST /tokenize` endpoint cases with `"type": "file"` in
63 + message content, which isn't implemented.
64 +
65 + 2. Skips tool_calls with `"type": "custom"` which schemathesis
66 + incorrectly generates instead of the valid `"type": "function"`.
67
68 Example test cases that are skipped:
69 curl -X POST -H 'Content-Type: application/json' \
66 - -d '{"messages": [{"role": "assistant"}, {"content": [{"file": {}, "type": "file"}], "role": "user"}]}' \
70 + -d '{"messages": [{"content": [{"file": {}, "type": "file"}], "role": "user"}]}' \
71 http://localhost:8000/tokenize
72
73 curl -X POST -H 'Content-Type: application/json' \
70 - -d '{"messages": [{"content": [{"file": {}, "type": "file"}], "role": "user"}]}' \
71 - http://localhost:8000/tokenize
74 + -d '{"messages": [{"role": "assistant", "tool_calls": [{"custom": {"input": "", "name": ""}, "id": "", "type": "custom"}]}]}' \
75 + http://localhost:8000/v1/chat/completions
76 """ # noqa: E501
73 - if (op.method.lower() == "post" and op.path == "/tokenize"
74 - and hasattr(case, "body") and isinstance(case.body, dict)
77 + if (hasattr(case, "body") and isinstance(case.body, dict)
78 and "messages" in case.body
79 and isinstance(case.body["messages"], list)
80 and len(case.body["messages"]) > 0):
81 +
82 for message in case.body["messages"]:
83 if not isinstance(message, dict):
84 continue
81 - content = message.get("content", [])
82 - if not isinstance(content, list) or len(content) == 0:
83 - continue
84 - if any(item.get("type") == "file" for item in content):
85 - return False
85 +
86 + # Check for invalid file type in tokenize endpoint
87 + if op.method.lower() == "post" and op.path == "/tokenize":
88 + content = message.get("content", [])
89 + if (isinstance(content, list) and len(content) > 0 and any(
90 + item.get("type") == "file" for item in content)):
91 + return False
92 +
93 + # Check for invalid tool_calls with non-function types
94 + tool_calls = message.get("tool_calls", [])
95 + if isinstance(tool_calls, list):
96 + for tool_call in tool_calls:
97 + if isinstance(tool_call, dict):
98 + if tool_call.get("type") != "function":
99 + return False
100 + if "custom" in tool_call:
101 + return False
102 return True
103
88 - return strategy.filter(no_file_type)
104 + return strategy.filter(no_invalid_types)
105
106
107 @schema.parametrize()