feat: add DeepSeek V4 reasoning support - #28945
Conversation
DeepSeek V4 (deepseek-v4-flash/pro) supports thinking mode via:
- top-level reasoning_effort parameter (high/max)
- extra_body.thinking {type: enabled/disabled}
Per DeepSeek docs:
- low/medium/high map to 'high'
- xhigh maps to 'max'
- thinking defaults to enabled
This adds DeepSeek-specific handling in both:
1. ChatCompletionsTransport.build_kwargs() — main chat path
2. chat_completion_helpers summary path — compression/summary path
Hermes previously only supported reasoning for:
- Kimi (reasoning_effort + extra_body.thinking)
- TokenHub (reasoning_effort)
- LM Studio (reasoning_effort)
- OpenRouter Anthropic/Claude/OpenAI (extra_body.reasoning)
DeepSeek via direct API was silently dropping reasoning config.
Fixes: reasoning config now properly forwarded to DeepSeek V4 models.
teknium1
left a comment
There was a problem hiding this comment.
Thanks for the DeepSeek V4 reasoning work. The premise still has value, but current main has moved the active DeepSeek request-shaping path since this PR was opened.
Problems
- The main chat-path part is now wired to the wrong layer. Current main resolves registered providers at
agent/chat_completion_helpers.py:725-764and passesprovider_profileinto the transport;agent/transports/chat_completions.py:526-538then delegates provider-specific kwargs toprofile.build_api_kwargs_extras(). Forprovider: deepseek, the new legacyis_deepseekflag path in this PR would be bypassed. - The effort mapping requested here is not fully present on current main:
plugins/model-providers/deepseek/__init__.py:72-80still forwardslowandmediumunchanged, while this PR maps them to DeepSeek'shigh. - The summary-path addition appears to re-enable thinking for
/reasoning none: in the PR diff,agent/chat_completion_helpers.py:1018always sendssummary_extra_body["thinking"] = {"type": "enabled"}when the DeepSeek summary effort branch runs.
Suggested changes
- Salvage the mapping into
plugins/model-providers/deepseek/__init__.py::DeepSeekProfile.build_api_kwargs_extras(). - Add targeted tests for
high,xhigh,low/medium, and disabled reasoning, plus a summary-path kwargs test if summary support is retained.
Automated hermes-sweeper review.
| @@ -283,6 +284,25 @@ def build_kwargs( | |||
| _kimi_effort = _e | |||
There was a problem hiding this comment.
On current main this lives in the bypassed legacy flag path for registered providers. provider: deepseek now routes through ProviderProfile, so this mapping should move into plugins/model-providers/deepseek/__init__.py::DeepSeekProfile.build_api_kwargs_extras().
| @@ -1009,6 +1016,9 @@ def handle_max_iterations(agent, messages: list, api_call_count: int) -> str: | |||
| summary_kwargs.update(agent._max_tokens_param(agent.max_tokens)) | |||
| if _lm_reasoning_effort is not None: | |||
| summary_kwargs["reasoning_effort"] = _lm_reasoning_effort | |||
There was a problem hiding this comment.
This re-enables DeepSeek thinking during summaries even for /reasoning none: the branch is entered for a truthy reasoning_config, then always sends thinking.type=enabled. The disabled case needs to mirror the main request path.
Summary
DeepSeek V4 (deepseek-v4-flash / deepseek-v4-pro) added thinking mode with client-controllable reasoning effort. Hermes previously had no DeepSeek-specific reasoning handling, so reasoning config was silently dropped when using the direct DeepSeek API.
What DeepSeek V4 supports
Per DeepSeek API docs:
reasoning_efforttop-level parameter: "high" or "max"extra_body.thinking.type: "enabled" or "disabled"low/medium→high,xhigh→maxhigheffortChanges
agent/transports/chat_completions.pyis_deepseekflagreasoning_effortmapped to DeepSeek's levelsextra_body.thinkingtoggle (enabled/disabled)agent/chat_completion_helpers.py_is_deepseekdetectionis_deepseekthrough to transportextra_body.reasoningfor OpenRouter/Anthropic, andreasoning_effortfor LM Studio)Before / After
/reasoning high+ DeepSeek direct APIreasoning_effort: high+thinking: enabled/reasoning xhigh+ DeepSeek direct APIreasoning_effort: max+thinking: enabled/reasoning none+ DeepSeek direct APIthinking: disabledTest plan
deepseekwith modeldeepseek-v4-pro/reasoning high→ verifyreasoning_effort: highsent/reasoning xhigh→ verifyreasoning_effort: maxsent/reasoning none→ verifythinking: disabledsentRelated