fix: forward reasoning_config to custom providers (vLLM, Ollama, etc.) - #20594
fix: forward reasoning_config to custom providers (vLLM, Ollama, etc.)#20594vominh1919 wants to merge 1 commit into
Conversation
Fixes NousResearch#20576 When using provider: custom with a vLLM-served thinking model (e.g. MiniMax-M2.7, DeepSeek-R1, GLM-4.x), the agent silently sent no thinking-budget control on the wire request because: 1. _supports_reasoning_extra_body() returned False for any base_url not in its hardcoded allowlist (OpenRouter, Nous, GitHub, LM Studio), so extra_body.reasoning was never emitted. 2. Even when reasoning was supported, the effort level was hardcoded to 'medium' instead of respecting the user's reasoning_config.effort. Root cause: _supports_reasoning_extra_body() had no check for custom providers, silently dropping the user's explicit reasoning_config. Fix: - In run_agent.py: add a 'custom' provider check that honors the user's reasoning_config (returns True when enabled is not explicitly False). - In chat_completions.py: use the user's configured effort level from reasoning_config instead of hardcoding 'medium'. This allows vLLM's reasoning_effort and thinking_token_budget parameters to be forwarded correctly, preventing runaway reasoning that consumes the entire max_tokens budget inside <think> blocks.
|
Would love to see this merged. Currently running into a lot of runaway reasoning. For those using qwen with vllm, i found I experienced this problem less in SGLang. |
|
@vominh1919 Thanks for this fix — I cherry-picked it locally and it does address the silent-drop path for One small concern: the current implementation clamps the forwarded effort to only: if _e in ("low", "medium", "high"):
_effort = _eFor Example: GLM-5.2 behind a custom endpoint accepts reasoning control through OpenAI-compatible request fields, and I don't think Hermes should necessarily map
Otherwise this fixes the binary on/off drop, but still loses higher-effort settings for custom endpoints that support them. |
|
Small correction after testing the cherry-picked code locally: on current I verified the emitted kwargs directly: profile = get_provider_profile("custom") # CustomProfile
ct.build_kwargs(
model="glm-5.2",
base_url="https://api.z.ai/api/coding/paas/v4",
reasoning_config={"enabled": True, "effort": "high"},
supports_reasoning=True,
provider_profile=profile,
request_overrides=None,
)["extra_body"]
# => {}So this PR fixes the legacy/custom gate, but it may not actually affect the current registered A user-level workaround is to put a static per-custom-provider override in config: custom_providers:
- name: z1
base_url: https://api.z.ai/api/coding/paas/v4
model: glm-5.2
extra_body:
reasoning:
enabled: true
effort: highThat works because custom-provider |
|
Thanks for identifying the silent custom-provider reasoning-control gap. This is now implemented on
|
Problem
When using
provider: customwith a vLLM-served thinking model (e.g. MiniMax-M2.7, DeepSeek-R1, GLM-4.x), the agent silently sends no thinking-budget control on the wire request. This causes:max_tokensbudget inside<think>blocks, producing emptycontentwithfinish_reason: "length"— no recovery path for the user.reasoning_config.effort, it's ignored for custom providers.Root cause:
_supports_reasoning_extra_body()inrun_agent.pyreturnsFalsefor anybase_urlnot in its hardcoded allowlist (OpenRouter, Nous, GitHub, LM Studio). Custom/vLLM providers are excluded, soextra_body.reasoningis never emitted — even when the user explicitly opted in viareasoning_config.Additionally, when reasoning is supported, the effort level was hardcoded to
"medium"instead of respecting the user'sreasoning_config.effort.Fix
run_agent.py: Added a"custom"provider check in_supports_reasoning_extra_body()that honors the user's explicitreasoning_config. ReturnsTruewhenenabledis not explicitly set toFalse.agent/transports/chat_completions.py: Changed the reasoning extra_body assembly to use the user's configured effort level fromreasoning_configinstead of hardcoding"medium". Consistent with how Kimi and TokenHub handle effort levels.Before vs After
provider: custom+reasoning_config: {effort: high}extra_body.reasoningNOT sentextra_body.reasoning = {enabled: true, effort: "high"}provider: custom+ no reasoning_configprovider: custom+reasoning_config: {enabled: false}reasoning_config: {effort: low}"medium""low"from user configRelated
Fixes #20576