feat: add DeepSeek V4 model support with thinking mode and reasoning effort (#5522) * fix: align DeepSeek provider with V4 API * Fix DeepSeek beta routing for standard chat completions * feat: add DeepSeek V4 model support with thinking mode and reasoning effort * Address DeepSeek review feedback * Set DeepSeek default model to v4 flash * fix: clean-up deprecated models, add migration * fix: move reasoning effort mapping to resolveReasoningEffort * fix: lint empty line * fix: remove duplicate code * fix: add coder model to migration logic --------- Co-authored-by: dclef <drclef233@gmail.com> Co-authored-by: Cohee <18619528+Cohee1207@users.noreply.github.com>

77cbcd877453d66f8069ff8bbae31b494395df73

Dclef <42974381+Dclef@users.noreply.github.com>

Signed
3 files changed, +23 -18Ignore whitespace
public/index.html+3 -5
@@ -2130,12 +2130,12 @@
21302130 <span data-i18n="Allows the model to return its thinking process.">
21312131 Allows the model to return its thinking process.
21322132 </span>
21332133 <strong data-i18n="This setting affects visibility only." data-source-mode="except" data-source="zai,moonshot,openrouter,deepseek">
21342134 This setting affects visibility only.
21352135 </strong>
21362136 </div>
21372137 </div>
21382138 <div class="flex-container flexFlowColumn wide100p textAlignCenter marginTop10" data-source="openai,custom,claude,xai,makersuite,vertexai,aimlapi,openrouter,pollinations,perplexity,cometapi,electronhub,azure_openai,chutes,nanogpt,deepseek">
21392139 <div class="flex-container oneline-dropdown" title="Constrains effort on reasoning for reasoning models.&#10;Reducing reasoning effort can result in faster responses and fewer tokens used on reasoning in a response." data-i18n="[title]Constrains effort on reasoning for reasoning models.">
21402140 <label for="openai_reasoning_effort">
21412141 <span data-i18n="Reasoning Effort">Reasoning Effort</span>
@@ -3735,9 +3735,7 @@
37353735 <div>
37363736 <h4 data-i18n="DeepSeek Model">DeepSeek Model</h4>
37373737 <select id="model_deepseek_select">
3738- <option value="deepseek-chat">deepseek-chat</option>
3738+ <option value="" data-i18n="-- Connect to the API --">-- Connect to the API --</option>
3739- <option value="deepseek-coder">deepseek-coder</option>
3740- <option value="deepseek-reasoner">deepseek-reasoner</option>
37413739 </select>
37423740 </div>
37433741 </div>
public/scripts/openai.js+16 -11
@@ -446,7 +446,7 @@ const default_settings = {
446446 electronhub_sort_models: 'alphabetically',
447447 electronhub_group_models: false,
448448 nanogpt_model: 'gpt-4o-mini',
449449 deepseek_model: 'deepseek-chatv4-flash',
450450 aimlapi_model: 'chatgpt-4o-latest',
451451 xai_model: 'grok-3-beta',
452452 pollinations_model: 'openai',
@@ -2501,6 +2501,7 @@ function getReasoningEffort(settings = null, model = null) {
25012501 chat_completion_sources.COMETAPI,
25022502 chat_completion_sources.ELECTRONHUB,
25032503 chat_completion_sources.CHUTES,
2504+ chat_completion_sources.DEEPSEEK,
25042505 ];
25052506
25062507 if (!reasoningEffortSources.includes(settings.chat_completion_source)) {
@@ -2508,6 +2509,17 @@ function getReasoningEffort(settings = null, model = null) {
25082509 }
25092510
25102511 function resolveReasoningEffort() {
2512+ if (settings.chat_completion_source === chat_completion_sources.DEEPSEEK) {
2513+ switch (settings.reasoning_effort) {
2514+ case reasoning_effort_types.auto:
2515+ return undefined;
2516+ case reasoning_effort_types.max:
2517+ return reasoning_effort_types.max;
2518+ default:
2519+ return reasoning_effort_types.high;
2520+ }
2521+ }
2522+
25112523 switch (settings.reasoning_effort) {
25122524 case reasoning_effort_types.auto:
25132525 return undefined;
@@ -4110,6 +4122,7 @@ function migrateChatCompletionSettings(settings) {
41104122 { oldKey: 'claude_use_sysprompt', oldValue: true, newKey: 'use_sysprompt', newValue: true },
41114123 { oldKey: 'use_makersuite_sysprompt', oldValue: true, newKey: 'use_sysprompt', newValue: true },
41124124 { oldKey: 'mistralai_model', oldValue: /^(mistral-medium|mistral-small)$/, newKey: 'mistralai_model', newValue: (settings.mistralai_model + '-latest') },
4125+ { oldKey: 'deepseek_model', oldValue: /^deepseek-(chat|reasoner|coder)$/, newKey: 'deepseek_model', newValue: 'deepseek-v4-flash' },
41134126 ];
41144127
41154128 for (const migration of migrateMap) {
@@ -5622,16 +5635,8 @@ async function onModelChange() {
56225635 }
56235636
56245637 if (oai_settings.chat_completion_source === chat_completion_sources.DEEPSEEK) {
5625- if (oai_settings.max_context_unlocked) {
5638+ const maxContext = oai_settings.max_context_unlocked ? unlocked_max : max_1mil;
56265639 $('#openai_max_context').attr('max', unlocked_maxmaxContext);
5627- } else if (['deepseek-reasoner', 'deepseek-chat'].includes(oai_settings.deepseek_model)) {
5628- $('#openai_max_context').attr('max', max_128k);
5629- } else if (oai_settings.deepseek_model == 'deepseek-coder') {
5630- $('#openai_max_context').attr('max', max_16k);
5631- } else {
5632- $('#openai_max_context').attr('max', max_64k);
5633- }
5634-
56355640 oai_settings.openai_max_context = Math.min(Number($('#openai_max_context').attr('max')), oai_settings.openai_max_context);
56365641 $('#openai_max_context').val(oai_settings.openai_max_context).trigger('input');
56375642 $('#temp_openai').attr('max', oai_max_temp).val(oai_settings.temp_openai).trigger('input');
src/endpoints/backends/chat-completions.js+4 -2
@@ -1074,9 +1074,10 @@ async function sendDeepSeekRequest(request, response) {
10741074 }
10751075
10761076 const processedMessages = addAssistantPrefix(postProcessPrompt(request.body.messages, PROMPT_PROCESSING_TYPE.SEMI_TOOLS, getPromptNames(request)), bodyParams.tools, 'prefix');
1077+ addReasoningContentToToolCalls(processedMessages);
10771078
10781079 if (/-reasoner/request.test(body.include_reasoning && request.body.model)reasoning_effort) {
1079- addReasoningContentToToolCalls(processedMessages);
1080+ bodyParams['reasoning_effort'] = request.body.reasoning_effort;
10801081 }
10811082
10821083 const requestBody = {
@@ -1090,6 +1091,7 @@ async function sendDeepSeekRequest(request, response) {
10901091 'top_p': request.body.top_p,
10911092 'stop': request.body.stop,
10921093 'seed': request.body.seed,
1094+ 'thinking': { type: request.body.include_reasoning ? 'enabled' : 'disabled' },
10931095 ...bodyParams,
10941096 };
10951097