test(deepseek): cover async tool filtering and document tool_choice assumption

Add an async_transform_request regression test so the sync and async tool
filtering paths cannot silently diverge, and document in _drop_unsupported_tools
that only non-function tools are dropped, so a function-named tool_choice always
references a surviving tool
This commit is contained in:
Jerry 2026-06-21 14:05:10 +08:00
parent 5bc0830e31
commit 31ea085077
2 changed files with 25 additions and 0 deletions

View file

@ -157,6 +157,11 @@ class DeepSeekChatConfig(OpenAIGPTConfig):
#30722). Drop the unsupported entries so the function tools still go
through, and drop the now-dangling tool_choice/parallel_tool_calls when
nothing callable survives.
Only non-`function` tools are ever dropped, so a `tool_choice` that names
a specific function still points at a surviving tool and is left intact;
`tool_choice`/`parallel_tool_calls` are cleared only when no function
tool remains.
"""
tools = optional_params.get("tools")
if not isinstance(tools, list) or not tools:

View file

@ -81,3 +81,23 @@ def test_transform_request_strips_unsupported_tools_from_body():
assert [tool["type"] for tool in body["tools"]] == ["function"]
assert body["tools"][0]["function"]["name"] == "shell"
async def test_async_transform_request_strips_unsupported_tools_from_body():
config = DeepSeekChatConfig()
body = await config.async_transform_request(
model="deepseek-chat",
messages=[{"role": "user", "content": "hi"}],
optional_params={
"tools": [
_function_tool("shell"),
{"type": "namespace", "name": "container.exec"},
],
"tool_choice": "auto",
},
litellm_params={},
headers={},
)
assert [tool["type"] for tool in body["tools"]] == ["function"]
assert body["tools"][0]["function"]["name"] == "shell"