Skip to content

feat(providers): support deepseek native api reasoning_ - #21052

Open
WuTianyi123 wants to merge 1 commit into
NousResearch:mainfrom
WuTianyi123:fix/deepseek-reasoning-effort
Open

feat(providers): support deepseek native api reasoning_#21052
WuTianyi123 wants to merge 1 commit into
NousResearch:mainfrom
WuTianyi123:fix/deepseek-reasoning-effort

Conversation

@WuTianyi123

Copy link
Copy Markdown
Contributor

What does this PR do?

Fix reasoning_effort being silently ignored when using the DeepSeek
native provider (api.deepseek.com). Two issues:

  1. DeepSeek's native API uses top-level reasoning_effort (high/max),
    not extra_body.reasoning. The base ProviderProfile returns ({}, {})
    for build_api_kwargs_extras, so the config was never sent.
  2. "max" was not in VALID_REASONING_EFFORTS — setting it caused
    Unknown reasoning_effort 'max', using default (medium).

Related Issue

N/A (no existing issue)

Type of Change

  • ✨ New feature (non-breaking change that adds functionality)
  • ✅ Tests (adding or improving test coverage)

Changes Made

  • hermes_constants.py: Add "max" to VALID_REASONING_EFFORTS
  • plugins/model-providers/deepseek/__init__.py: New DeepSeekProfile class
    with build_api_kwargs_extras emitting top-level reasoning_effort,
    mapping: low/medium/minimal"high", xhigh/max"max"
  • run_agent.py: Summary path handles deepseek like LM Studio (top-level
    reasoning_effort, not extra_body.reasoning)
  • cli.py: /reasoning help text updated
  • cli-config.yaml.example: Options comment updated
  • batch_runner.py: Docstring + valid_efforts list updated
  • tests/providers/test_transport_parity.py: 7 new TestDeepSeekParity tests

How to Test

  1. pytest tests/providers/test_transport_parity.py -q (26→33 tests, deepseek
    mapping coverage)
  2. pytest tests/run_agent/test_run_agent.py -k reasoning -q (35 reasoning tests)
  3. pytest tests/providers/ -q (90 provider tests)
  4. Manual: set reasoning_effort: xhigh with provider: deepseek, verify
    reasoning_effort: max is sent in API request

Checklist

Code

  • I've read the Contributing Guide
  • My commit messages follow Conventional Commits
  • I searched for existing PRs to make sure this isn't a duplicate
  • My PR contains only changes related to this fix/feature
  • I've run pytest tests/ -q and all tests pass
  • I've added tests for my changes
  • I've tested on my platform: Ubuntu 24.04

Documentation & Housekeeping

  • I've updated relevant documentation (docstrings updated) — or N/A
  • I've updated cli-config.yaml.example — config comment updated
  • N/A — no architecture/workflow changes
  • I've considered cross-platform impact — N/A (provider plugin, no OS dependency)
  • N/A — no tool behavior change

Screenshots / Logs

Before (reasoning_effort: xhigh with provider: deepseek):

  • _supports_reasoning_extra_body() returned False
  • reasoning_effort was silently dropped from API request
    After:
  • DeepSeek profile emits reasoning_effort as top-level param
  • xhigh"max", medium"high" (per DeepSeek API spec)
  • Transport parity tests verify all mappings

DeepSeek's native API accepts top-level reasoning_effort (high/max),
not extra_body.reasoning. Previously the DeepSeek profile used the
base ProviderProfile which returned ({}, {}) for build_api_kwargs_extras,
so reasoning_effort config was silently ignored when using the DeepSeek
native provider (api.deepseek.com).

Changes:
- Add 'max' to VALID_REASONING_EFFORTS in hermes_constants.py
- DeepSeekProfile overrides build_api_kwargs_extras to emit
  reasoning_effort as top-level param with value mapping:
  low/medium/minimal → high, xhigh/max → max
- Summary path in run_agent.py handles deepseek top-level
  reasoning_effort (like LM Studio), bypassing extra_body.reasoning
- Update UI help texts and config example comments to include 'max'

Tests: 7 new transport parity tests in TestDeepSeekParity.
All existing tests pass.

@teknium1 teknium1 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for identifying the native DeepSeek reasoning_effort gap. The normal request path is now implemented by merged PR #26648 (cd9470f41638bd515db096cd934c463205790110): plugins/model-providers/deepseek/__init__.py:47-82 emits both top-level reasoning_effort and extra_body.thinking, and agent/transports/chat_completions.py:562-575 applies the profile extras.

Problems

  • The remaining iteration-limit summary path still calls chat.completions.create() directly. It handles only LM Studio at agent/chat_completion_helpers.py:1650-1691, and repeats the same request construction on retry at :1774-1787.
  • The PR's summary branch adds only reasoning_effort; it would not include DeepSeek V4's extra_body.thinking control that the canonical profile emits at plugins/model-providers/deepseek/__init__.py:67-80.

Suggested changes

  • Salvage the summary-path portion into agent/chat_completion_helpers.py, preferably by deriving the summary extras from the registered provider profile so its wire shape cannot drift from the main transport.
  • Add DeepSeek V4 initial-summary and retry-summary tests covering enabled and disabled reasoning.

Automated hermes-sweeper review.

Comment thread run_agent.py
@@ -10444,11 +10470,18 @@ def _handle_max_iterations(self, messages: list, api_call_count: int) -> str:
(self.provider or "").strip().lower() == "lmstudio"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This bypasses the generic extra_body.reasoning path for DeepSeek, but the subsequent summary kwargs add only reasoning_effort. DeepSeek V4 also needs its extra_body.thinking control; please source both extras from the DeepSeek provider-profile contract so the direct summary request matches normal transport calls.

@teknium1 teknium1 added sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform labels Jul 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint comp/plugins Plugin system and bundled plugins P2 Medium — degraded but workaround exists provider/deepseek DeepSeek API sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades type/feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants