mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2026-07-06 05:55:28 +08:00
hotfix(models): add DeepSeek V4+ model support with reasoning effort (#14551)
### What this PR does
Adds wildcard detection and reasoning effort support for DeepSeek V4+
models (`deepseek-v4-flash`, `deepseek-v4-pro`, and future versions like
V5+).
Before this PR: DeepSeek V4 models are not recognized as reasoning
models, so the thinking toggle and effort selector don't appear in the
UI.
After this PR: V4+ models are auto-detected via a generic regex
(`deepseek-v{N>=4}`), with proper reasoning effort control (`high` /
`max`).
### Why we need it and why it was done in this way
DeepSeek released V4 models with a new reasoning effort API
(`reasoning_effort: "high" | "max"`) alongside the existing `thinking: {
type: "enabled" }` control. The existing
`isDeepSeekHybridInferenceModel()` regex only matched V3.x patterns and
`deepseek-chat`, missing V4 entirely.
Key design decisions:
- **Wildcard regex** (`deepseek-v([4-9]|\d{2,})`) instead of hardcoding
V4 — future versions (V5, V6...) are automatically covered
- **V3 regex unchanged** — `deepseek-v3` (plain) doesn't support
thinking on some third-party providers, so the existing suffix
requirement is preserved
- **UI uses `xhigh` → API maps to `max`** — reuses existing
`ReasoningEffortOption` type without extending it, since `max` is not in
`OpenAI.ReasoningEffort`
- **V4+ defaults to thinking enabled** — unlike V3.x which defaults to
non-thinking, V4 requires explicit `{ thinking: { type: 'disabled' } }`
to turn off
### Changes (3 files)
1. **`src/renderer/src/types/index.ts`** — Add `'deepseek_v4'` to
`ThinkModelTypes`
2. **`src/renderer/src/config/models/reasoning.ts`**:
- New `isDeepSeekV4PlusModel()` — generic regex for V4+ model IDs
- `isDeepSeekHybridInferenceModel()` now includes V4+ via `||
isDeepSeekV4PlusModel(model)`
- `_getThinkModelType()` returns `'deepseek_v4'` (checked before
`deepseek_hybrid`)
- `MODEL_SUPPORTED_REASONING_EFFORT.deepseek_v4`: `['high', 'xhigh']`
- `MODEL_SUPPORTED_OPTIONS.deepseek_v4`: `['default', 'none', 'high',
'xhigh']`
3. **`src/renderer/src/aiCore/utils/reasoning.ts`**:
- V4+ effort params: `{ thinking: { type: 'enabled' }, reasoning_effort:
'high' | 'max' }`
- `none` handling: `{ thinking: { type: 'disabled' } }` (V4 defaults to
thinking on)
### Breaking changes
None.
### Checklist
- [x] PR: The PR description is expressive enough and will help future
contributors
- [x] Code: Write code that humans can understand and Keep it simple
- [x] Refactor: You have left the code cleaner than you found it (Boy
Scout Rule)
- [x] Self-review: I have reviewed my own code before requesting review
from others
### Release note
```release-note
Support DeepSeek V4+ models (deepseek-v4-flash, deepseek-v4-pro) with reasoning effort control (high/max)
```
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Signed-off-by: Siin Xu <31815270+SiinXu@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -12,6 +12,7 @@ import {
|
||||
getModelSupportedReasoningEffortOptions,
|
||||
isClaude46SeriesModel,
|
||||
isDeepSeekHybridInferenceModel,
|
||||
isDeepSeekV4PlusModel,
|
||||
isDoubaoSeed18Model,
|
||||
isDoubaoSeedAfter251015,
|
||||
isDoubaoThinkingAutoModel,
|
||||
@@ -185,7 +186,12 @@ export function getReasoningEffort(assistant: Assistant, model: Model): Reasonin
|
||||
return { thinking: { type: 'disabled' } }
|
||||
}
|
||||
|
||||
// Deepseek, default behavior is non-thinking
|
||||
// DeepSeek V4+ defaults to thinking enabled, explicitly disable it
|
||||
if (isDeepSeekV4PlusModel(model)) {
|
||||
return { thinking: { type: 'disabled' } }
|
||||
}
|
||||
|
||||
// DeepSeek V3.x hybrid, default behavior is non-thinking
|
||||
if (isDeepSeekHybridInferenceModel(model)) {
|
||||
return {}
|
||||
}
|
||||
@@ -341,6 +347,15 @@ export function getReasoningEffort(assistant: Assistant, model: Model): Reasonin
|
||||
return {}
|
||||
}
|
||||
|
||||
// DeepSeek V4+ models support reasoning_effort: "high" | "max" alongside thinking control
|
||||
// UI uses "xhigh" which maps to API's "max"; all other effort levels map to "high"
|
||||
if (isDeepSeekV4PlusModel(model)) {
|
||||
return {
|
||||
thinking: { type: 'enabled' as const },
|
||||
reasoning_effort: reasoningEffort === 'xhigh' ? ('max' as OpenAIReasoningEffort) : 'high'
|
||||
}
|
||||
}
|
||||
|
||||
// DeepSeek hybrid inference models, v3.1 and maybe more in the future
|
||||
// 不同的 provider 有不同的思考控制方式,在这里统一解决
|
||||
if (isDeepSeekHybridInferenceModel(model)) {
|
||||
|
||||
@@ -79,6 +79,7 @@ export const MODEL_SUPPORTED_REASONING_EFFORT = {
|
||||
zhipu: ['auto'] as const,
|
||||
perplexity: ['low', 'medium', 'high'] as const,
|
||||
deepseek_hybrid: ['auto'] as const,
|
||||
deepseek_v4: ['high', 'xhigh'] as const,
|
||||
kimi_k2_5: ['none', 'auto'] as const,
|
||||
// Claude 3.7, 4.0, 4.5 reasoning models
|
||||
claude: ['low', 'medium', 'high'] as const,
|
||||
@@ -118,6 +119,7 @@ export const MODEL_SUPPORTED_OPTIONS: ThinkingOptionConfig = {
|
||||
zhipu: ['default', 'none', ...MODEL_SUPPORTED_REASONING_EFFORT.zhipu] as const,
|
||||
perplexity: ['default', ...MODEL_SUPPORTED_REASONING_EFFORT.perplexity] as const,
|
||||
deepseek_hybrid: ['default', 'none', ...MODEL_SUPPORTED_REASONING_EFFORT.deepseek_hybrid] as const,
|
||||
deepseek_v4: ['default', 'none', ...MODEL_SUPPORTED_REASONING_EFFORT.deepseek_v4] as const,
|
||||
kimi_k2_5: ['default', ...MODEL_SUPPORTED_REASONING_EFFORT.kimi_k2_5] as const,
|
||||
claude: ['default', 'none', ...MODEL_SUPPORTED_REASONING_EFFORT.claude] as const,
|
||||
claude46: ['default', 'none', ...MODEL_SUPPORTED_REASONING_EFFORT.claude46] as const
|
||||
@@ -202,6 +204,8 @@ const _getThinkModelType = (model: Model): ThinkingModelType => {
|
||||
thinkingModelType = 'perplexity'
|
||||
} else if (isSupportedThinkingTokenZhipuModel(model)) {
|
||||
thinkingModelType = 'zhipu'
|
||||
} else if (isDeepSeekV4PlusModel(model)) {
|
||||
thinkingModelType = 'deepseek_v4'
|
||||
} else if (isDeepSeekHybridInferenceModel(model)) {
|
||||
thinkingModelType = 'deepseek_hybrid'
|
||||
} else if (isSupportedThinkingTokenMiMoModel(model)) {
|
||||
@@ -630,6 +634,19 @@ export const isSupportedThinkingTokenKimiModel = (model: Model): boolean => {
|
||||
return idResult || nameResult
|
||||
}
|
||||
|
||||
/**
|
||||
* Matches DeepSeek V4+ models (e.g., deepseek-v4-flash, deepseek-v4-pro, deepseek-v5-xxx).
|
||||
* V4+ models default to thinking enabled and support reasoning_effort: "high" | "max".
|
||||
*/
|
||||
export const isDeepSeekV4PlusModel = (model: Model) => {
|
||||
const { idResult, nameResult } = withModelIdAndNameAsId(model, (model) => {
|
||||
const modelId = getLowerBaseModelName(model.id)
|
||||
// Match deepseek-v{N} where N >= 4, with any optional suffix
|
||||
return /(\w+-)?deepseek-v([4-9]|\d{2,})([.-]\w+)*$/.test(modelId)
|
||||
})
|
||||
return idResult || nameResult
|
||||
}
|
||||
|
||||
export const isDeepSeekHybridInferenceModel = (model: Model) => {
|
||||
const { idResult, nameResult } = withModelIdAndNameAsId(model, (model) => {
|
||||
const modelId = getLowerBaseModelName(model.id)
|
||||
@@ -647,7 +664,7 @@ export const isDeepSeekHybridInferenceModel = (model: Model) => {
|
||||
modelId.includes('deepseek-chat')
|
||||
)
|
||||
})
|
||||
return idResult || nameResult
|
||||
return idResult || nameResult || isDeepSeekV4PlusModel(model)
|
||||
}
|
||||
|
||||
export const isLingReasoningModel = (model?: Model): boolean => {
|
||||
|
||||
@@ -126,6 +126,7 @@ const ThinkModelTypes = [
|
||||
'zhipu',
|
||||
'perplexity',
|
||||
'deepseek_hybrid',
|
||||
'deepseek_v4',
|
||||
'kimi_k2_5',
|
||||
'claude',
|
||||
'claude46'
|
||||
|
||||
Reference in New Issue
Block a user