Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 20 additions & 3 deletions plugins/model-providers/qwen-oauth/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,11 +89,28 @@ def build_api_kwargs_extras(
qwen_session_metadata: dict | None = None,
**context,
) -> tuple[dict[str, Any], dict[str, Any]]:
"""Qwen metadata goes to top-level api_kwargs, not extra_body."""
top_level = {}
"""Build Qwen's explicit thinking contract.

Qwen-compatible endpoints default to server-side ``auto`` when this
field is omitted. Hermes must not rely on that implicit mode: unset
reasoning is the safe utility/coding mode, while an explicit enabled
config opts into thinking. The 32K budget is deliberately below the
64K completion cap so an enabled request retains room for visible
answer tokens.
"""
top_level: dict[str, Any] = {}
if qwen_session_metadata:
top_level["metadata"] = qwen_session_metadata
return {}, top_level

enabled = bool(
isinstance(reasoning_config, dict)
and type(reasoning_config.get("enabled")) is bool
and reasoning_config["enabled"] is True
)
extra_body: dict[str, Any] = {"enable_thinking": enabled}
if enabled:
extra_body["thinking_budget"] = 32768
return extra_body, top_level


qwen = QwenProfile(
Expand Down
50 changes: 50 additions & 0 deletions tests/providers/test_provider_profiles.py
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,56 @@ def test_metadata_top_level(self):
assert tl["metadata"] == meta
assert "metadata" not in eb

def test_reasoning_disabled_unless_enabled_is_true(self):
p = get_provider_profile("qwen-oauth")
assert p is not None
disabled_configs: tuple[object, ...] = (
None,
{},
{"effort": "high"},
{"enabled": False},
{"enabled": "false"},
{"enabled": 1},
{"enabled": None},
[],
"malformed",
)
for config in disabled_configs:
eb, _ = p.build_api_kwargs_extras(reasoning_config=config)
assert eb == {"enable_thinking": False}, config
enabled_with_effort = (
{"enabled": True},
{"enabled": True, "effort": "none"},
{"enabled": True, "effort": " NONE "},
{"enabled": True, "effort": "NoNe"},
{"enabled": True, "effort": "high"},
{"enabled": True, "effort": object()},
)
for config in enabled_with_effort:
eb, _ = p.build_api_kwargs_extras(reasoning_config=config)
assert eb == {"enable_thinking": True, "thinking_budget": 32768}, config
eb, _ = p.build_api_kwargs_extras(reasoning_config={"enabled": "malformed"})
assert eb == {"enable_thinking": False}

def test_reasoning_is_enabled_with_bounded_budget_and_headroom(self):
p = get_provider_profile("qwen-oauth")
assert p is not None
eb, _ = p.build_api_kwargs_extras(
reasoning_config={"enabled": True, "effort": "high"}
)
assert eb == {"enable_thinking": True, "thinking_budget": 32768}
assert p.default_max_tokens > eb["thinking_budget"]

def test_metadata_is_preserved_with_reasoning_contract(self):
p = get_provider_profile("qwen-oauth")
assert p is not None
meta = {"sessionId": "s123", "promptId": "p456"}
eb, tl = p.build_api_kwargs_extras(
reasoning_config={"enabled": True}, qwen_session_metadata=meta
)
assert eb == {"enable_thinking": True, "thinking_budget": 32768}
assert tl == {"metadata": meta}




Loading