From e264b5b05262ac32830b8077540a39c5b5e01b83 Mon Sep 17 00:00:00 2001 From: Xin Rui <71483384+Konjac-XZ@users.noreply.github.com> Date: Fri, 13 Jun 2025 00:03:58 +0800 Subject: [PATCH] feat: Support reasoning control for Doubao/Mistral models. (#7116) * feat: Support reasoning control for Doubao models. * feat: Enhance model handling and support for Doubao and Gemini in API clients - Added support for Doubao thinking modes in OpenAIAPIClient and GeminiAPIClient. - Introduced GEMINI_FLASH_MODEL_REGEX for model identification. - Updated models.ts to include new Doubao and Gemini model regex patterns. - Added new image asset for ChatGPT in models. - Enhanced reasoning control and token budget handling for Doubao models. - Improved the Inputbar's ThinkingButton component to accommodate new thinking options. --------- Co-authored-by: suyao --- .../aiCore/clients/gemini/GeminiAPIClient.ts | 9 +++- .../aiCore/clients/openai/OpenAIApiClient.ts | 40 +++++++++++++++++- .../src/assets/images/models/gpt_image_1.png | Bin 0 -> 20281 bytes src/renderer/src/config/models.ts | 40 ++++++++++++++++-- .../pages/home/Inputbar/ThinkingButton.tsx | 19 +++++++-- src/renderer/src/types/sdk.ts | 2 +- 6 files changed, 97 insertions(+), 13 deletions(-) create mode 100644 src/renderer/src/assets/images/models/gpt_image_1.png diff --git a/src/renderer/src/aiCore/clients/gemini/GeminiAPIClient.ts b/src/renderer/src/aiCore/clients/gemini/GeminiAPIClient.ts index b40aff9182..bc848df7f9 100644 --- a/src/renderer/src/aiCore/clients/gemini/GeminiAPIClient.ts +++ b/src/renderer/src/aiCore/clients/gemini/GeminiAPIClient.ts @@ -19,7 +19,13 @@ import { } from '@google/genai' import { nanoid } from '@reduxjs/toolkit' import { GenericChunk } from '@renderer/aiCore/middleware/schemas' -import { findTokenLimit, isGeminiReasoningModel, isGemmaModel, isVisionModel } from '@renderer/config/models' +import { + findTokenLimit, + GEMINI_FLASH_MODEL_REGEX, + isGeminiReasoningModel, + isGemmaModel, + isVisionModel +} from '@renderer/config/models' import { CacheService } from '@renderer/services/CacheService' import { estimateTextTokens } from '@renderer/services/TokenService' import { @@ -378,7 +384,6 @@ export class GeminiAPIClient extends BaseApiClient< private getBudgetToken(assistant: Assistant, model: Model) { if (isGeminiReasoningModel(model)) { const reasoningEffort = assistant?.settings?.reasoning_effort - const GEMINI_FLASH_MODEL_REGEX = new RegExp('gemini-.*-flash.*$') // 如果thinking_budget是undefined,不思考 if (reasoningEffort === undefined) { diff --git a/src/renderer/src/aiCore/clients/openai/OpenAIApiClient.ts b/src/renderer/src/aiCore/clients/openai/OpenAIApiClient.ts index 1a78aea0f8..07359c837f 100644 --- a/src/renderer/src/aiCore/clients/openai/OpenAIApiClient.ts +++ b/src/renderer/src/aiCore/clients/openai/OpenAIApiClient.ts @@ -2,12 +2,15 @@ import { DEFAULT_MAX_TOKENS } from '@renderer/config/constant' import Logger from '@renderer/config/logger' import { findTokenLimit, + GEMINI_FLASH_MODEL_REGEX, getOpenAIWebSearchParams, + isDoubaoThinkingAutoModel, isReasoningModel, isSupportedReasoningEffortGrokModel, isSupportedReasoningEffortModel, isSupportedReasoningEffortOpenAIModel, isSupportedThinkingTokenClaudeModel, + isSupportedThinkingTokenDoubaoModel, isSupportedThinkingTokenGeminiModel, isSupportedThinkingTokenModel, isSupportedThinkingTokenQwenModel, @@ -92,6 +95,23 @@ export class OpenAIAPIClient extends OpenAIBaseClient< return {} } const reasoningEffort = assistant?.settings?.reasoning_effort + + // Doubao 思考模式支持 + if (isSupportedThinkingTokenDoubaoModel(model)) { + // reasoningEffort 为空,默认开启 enabled + if (!reasoningEffort) { + return { thinking: { type: 'disabled' } } + } + if (reasoningEffort === 'high') { + return { thinking: { type: 'enabled' } } + } + if (reasoningEffort === 'auto' && isDoubaoThinkingAutoModel(model)) { + return { thinking: { type: 'auto' } } + } + // 其他情况不带 thinking 字段 + return {} + } + if (!reasoningEffort) { if (isSupportedThinkingTokenQwenModel(model)) { return { enable_thinking: false } @@ -106,9 +126,14 @@ export class OpenAIAPIClient extends OpenAIBaseClient< if (this.provider.id === 'openrouter') { return { reasoning: { max_tokens: 0, exclude: true } } } - return { - reasoning_effort: 'none' + if (GEMINI_FLASH_MODEL_REGEX.test(model.id)) { + return { reasoning_effort: 'none' } } + return {} + } + + if (isSupportedThinkingTokenDoubaoModel(model)) { + return { thinking: { type: 'disabled' } } } return {} @@ -164,6 +189,17 @@ export class OpenAIAPIClient extends OpenAIBaseClient< } } + // Doubao models + if (isSupportedThinkingTokenDoubaoModel(model)) { + if (assistant.settings?.reasoning_effort === 'high') { + return { + thinking: { + type: 'enabled' + } + } + } + } + // Default case: no special thinking settings return {} } diff --git a/src/renderer/src/assets/images/models/gpt_image_1.png b/src/renderer/src/assets/images/models/gpt_image_1.png new file mode 100644 index 0000000000000000000000000000000000000000..30f2f2708f1d4fe2337ab9bca5aea05ea3b679ea GIT binary patch literal 20281 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 Q-~a#s07*qoM6N<$f>aHQuK)l5 literal 0 HcmV?d00001 diff --git a/src/renderer/src/config/models.ts b/src/renderer/src/config/models.ts index 361478e411..78f4ff3d0b 100644 --- a/src/renderer/src/config/models.ts +++ b/src/renderer/src/config/models.ts @@ -55,6 +55,7 @@ import { default as ChatGptModelLogoDakr, default as ChatGPTo1ModelLogoDark } from '@renderer/assets/images/models/gpt_dark.png' +import ChatGPTImageModelLogo from '@renderer/assets/images/models/gpt_image_1.png' import ChatGPTo1ModelLogo from '@renderer/assets/images/models/gpt_o1.png' import GrokModelLogo from '@renderer/assets/images/models/grok.png' import GrokModelLogoDark from '@renderer/assets/images/models/grok_dark.png' @@ -181,7 +182,8 @@ const visionAllowedModels = [ 'o4(?:-[\\w-]+)?', 'deepseek-vl(?:[\\w-]+)?', 'kimi-latest', - 'gemma-3(?:-[\\w-]+)' + 'gemma-3(?:-[\\w-]+)', + 'doubao-1.6-seed(?:-[\\w-]+)' ] const visionExcludedModels = [ @@ -291,6 +293,7 @@ export function getModelLogo(modelId: string) { o1: isLight ? ChatGPTo1ModelLogo : ChatGPTo1ModelLogoDark, o3: isLight ? ChatGPTo1ModelLogo : ChatGPTo1ModelLogoDark, o4: isLight ? ChatGPTo1ModelLogo : ChatGPTo1ModelLogoDark, + 'gpt-image': ChatGPTImageModelLogo, 'gpt-3': isLight ? ChatGPT35ModelLogo : ChatGPT35ModelLogoDark, 'gpt-4': isLight ? ChatGPT4ModelLogo : ChatGPT4ModelLogoDark, gpts: isLight ? ChatGPT4ModelLogo : ChatGPT4ModelLogoDark, @@ -312,6 +315,7 @@ export function getModelLogo(modelId: string) { mistral: isLight ? MistralModelLogo : MistralModelLogoDark, codestral: CodestralModelLogo, ministral: isLight ? MistralModelLogo : MistralModelLogoDark, + magistral: isLight ? MistralModelLogo : MistralModelLogoDark, moonshot: isLight ? MoonshotModelLogo : MoonshotModelLogoDark, kimi: isLight ? MoonshotModelLogo : MoonshotModelLogoDark, phi: isLight ? MicrosoftModelLogo : MicrosoftModelLogoDark, @@ -2411,7 +2415,8 @@ export function isSupportedThinkingTokenModel(model?: Model): boolean { return ( isSupportedThinkingTokenGeminiModel(model) || isSupportedThinkingTokenQwenModel(model) || - isSupportedThinkingTokenClaudeModel(model) + isSupportedThinkingTokenClaudeModel(model) || + isSupportedThinkingTokenDoubaoModel(model) ) } @@ -2493,6 +2498,14 @@ export function isSupportedThinkingTokenQwenModel(model?: Model): boolean { ) } +export function isSupportedThinkingTokenDoubaoModel(model?: Model): boolean { + if (!model) { + return false + } + + return DOUBAO_THINKING_MODEL_REGEX.test(model.id) +} + export function isClaudeReasoningModel(model?: Model): boolean { if (!model) { return false @@ -2513,7 +2526,12 @@ export function isReasoningModel(model?: Model): boolean { } if (model.provider === 'doubao') { - return REASONING_REGEX.test(model.name) || model.type?.includes('reasoning') || false + return ( + REASONING_REGEX.test(model.name) || + model.type?.includes('reasoning') || + isSupportedThinkingTokenDoubaoModel(model) || + false + ) } if ( @@ -2522,7 +2540,8 @@ export function isReasoningModel(model?: Model): boolean { isGeminiReasoningModel(model) || isQwenReasoningModel(model) || isGrokReasoningModel(model) || - model.id.includes('glm-z1') + model.id.includes('glm-z1') || + model.id.includes('magistral') ) { return true } @@ -2804,3 +2823,16 @@ export const findTokenLimit = (modelId: string): { min: number; max: number } | } return undefined } + +// Doubao 支持思考模式的模型正则 +export const DOUBAO_THINKING_MODEL_REGEX = + /doubao-(?:1(\.|-5)-thinking-vision-pro|1(\.|-)5-thinking-pro-m|seed-1\.6|seed-1\.6-flash)(?:-[\\w-]+)?/i + +// 支持 auto 的 Doubao 模型 +export const DOUBAO_THINKING_AUTO_MODEL_REGEX = /doubao-(?:1-5-thinking-pro-m|seed-1.6)(?:-[\\w-]+)?/i + +export function isDoubaoThinkingAutoModel(model: Model): boolean { + return DOUBAO_THINKING_AUTO_MODEL_REGEX.test(model.id) +} + +export const GEMINI_FLASH_MODEL_REGEX = new RegExp('gemini-.*-flash.*$') diff --git a/src/renderer/src/pages/home/Inputbar/ThinkingButton.tsx b/src/renderer/src/pages/home/Inputbar/ThinkingButton.tsx index 2caef6c158..21db131cef 100644 --- a/src/renderer/src/pages/home/Inputbar/ThinkingButton.tsx +++ b/src/renderer/src/pages/home/Inputbar/ThinkingButton.tsx @@ -7,7 +7,9 @@ import { } from '@renderer/components/Icons/SVGIcon' import { useQuickPanel } from '@renderer/components/QuickPanel' import { + isDoubaoThinkingAutoModel, isSupportedReasoningEffortGrokModel, + isSupportedThinkingTokenDoubaoModel, isSupportedThinkingTokenGeminiModel, isSupportedThinkingTokenQwenModel } from '@renderer/config/models' @@ -35,13 +37,14 @@ const MODEL_SUPPORTED_OPTIONS: Record = { default: ['off', 'low', 'medium', 'high'], grok: ['off', 'low', 'high'], gemini: ['off', 'low', 'medium', 'high', 'auto'], - qwen: ['off', 'low', 'medium', 'high'] + qwen: ['off', 'low', 'medium', 'high'], + doubao: ['off', 'auto', 'high'] } // 选项转换映射表:当选项不支持时使用的替代选项 const OPTION_FALLBACK: Record = { off: 'off', - low: 'low', + low: 'high', medium: 'high', // medium -> high (for Grok models) high: 'high', auto: 'high' // auto -> high (for non-Gemini models) @@ -55,6 +58,7 @@ const ThinkingButton: FC = ({ ref, model, assistant, ToolbarButton }): Re const isGrokModel = isSupportedReasoningEffortGrokModel(model) const isGeminiModel = isSupportedThinkingTokenGeminiModel(model) const isQwenModel = isSupportedThinkingTokenQwenModel(model) + const isDoubaoModel = isSupportedThinkingTokenDoubaoModel(model) const currentReasoningEffort = useMemo(() => { return assistant.settings?.reasoning_effort || 'off' @@ -65,13 +69,20 @@ const ThinkingButton: FC = ({ ref, model, assistant, ToolbarButton }): Re if (isGeminiModel) return 'gemini' if (isGrokModel) return 'grok' if (isQwenModel) return 'qwen' + if (isDoubaoModel) return 'doubao' return 'default' - }, [isGeminiModel, isGrokModel, isQwenModel]) + }, [isGeminiModel, isGrokModel, isQwenModel, isDoubaoModel]) // 获取当前模型支持的选项 const supportedOptions = useMemo(() => { + if (modelType === 'doubao') { + if (isDoubaoThinkingAutoModel(model)) { + return ['off', 'auto', 'high'] as ThinkingOption[] + } + return ['off', 'high'] as ThinkingOption[] + } return MODEL_SUPPORTED_OPTIONS[modelType] - }, [modelType]) + }, [model, modelType]) // 检查当前设置是否与当前模型兼容 useEffect(() => { diff --git a/src/renderer/src/types/sdk.ts b/src/renderer/src/types/sdk.ts index cef04febff..c066952ec1 100644 --- a/src/renderer/src/types/sdk.ts +++ b/src/renderer/src/types/sdk.ts @@ -47,7 +47,7 @@ export type RequestOptions = Anthropic.RequestOptions | OpenAI.RequestOptions | type OpenAIParamsWithoutReasoningEffort = Omit export type ReasoningEffortOptionalParams = { - thinking?: { type: 'disabled' | 'enabled'; budget_tokens?: number } + thinking?: { type: 'disabled' | 'enabled' | 'auto'; budget_tokens?: number } reasoning?: { max_tokens?: number; exclude?: boolean; effort?: string } | OpenAI.Reasoning reasoning_effort?: OpenAI.Chat.Completions.ChatCompletionCreateParams['reasoning_effort'] | 'none' | 'auto' enable_thinking?: boolean