From 57fa0aad38a95f236bcce92760f535f97c16393c Mon Sep 17 00:00:00 2001 From: Asurada <43401755+ousugo@users.noreply.github.com> Date: Thu, 10 Apr 2025 18:43:20 +0800 Subject: [PATCH] feat(xAI): Add support for Grok-3-mini and update reasoning effort logic (#4657) * feat(models): add grok-3-mini support and update reasoning effort logic in SettingsTab and OpenAIProvider * feat(settings): update reasoning effort logic for Grok models and enhance localization in multiple languages * fix(models): correct spelling of reasoning in model support functions * fix(settings): correct spelling of reasoning_effort in OpenAIProvider --- src/renderer/src/config/models.ts | 23 +++++++++-- src/renderer/src/i18n/locales/en-us.json | 2 +- src/renderer/src/i18n/locales/ja-jp.json | 2 +- src/renderer/src/i18n/locales/ru-ru.json | 2 +- src/renderer/src/i18n/locales/zh-cn.json | 2 +- src/renderer/src/i18n/locales/zh-tw.json | 2 +- .../src/pages/home/Tabs/SettingsTab.tsx | 39 ++++++++++++++----- .../providers/AiProvider/OpenAIProvider.ts | 7 ++++ 8 files changed, 62 insertions(+), 17 deletions(-) diff --git a/src/renderer/src/config/models.ts b/src/renderer/src/config/models.ts index 7291a37b..12a88c4e 100644 --- a/src/renderer/src/config/models.ts +++ b/src/renderer/src/config/models.ts @@ -186,7 +186,7 @@ export const TEXT_TO_IMAGE_REGEX = /flux|diffusion|stabilityai|sd-|dall|cogview| // Reasoning models export const REASONING_REGEX = - /^(o\d+(?:-[\w-]+)?|.*\b(?:reasoner|thinking)\b.*|.*-[rR]\d+.*|.*\bqwq(?:-[\w-]+)?\b.*|.*\bhunyuan-t1(?:-[\w-]+)?\b.*|.*\bglm-zero-preview\b.*)$/i + /^(o\d+(?:-[\w-]+)?|.*\b(?:reasoner|thinking)\b.*|.*-[rR]\d+.*|.*\bqwq(?:-[\w-]+)?\b.*|.*\bhunyuan-t1(?:-[\w-]+)?\b.*|.*\bglm-zero-preview\b.*|.*\bgrok-3-mini(?:-[\w-]+)?\b.*)$/i // Embedding models export const EMBEDDING_REGEX = @@ -2202,12 +2202,29 @@ export function isOpenAIWebSearch(model: Model): boolean { return model.id.includes('gpt-4o-search-preview') || model.id.includes('gpt-4o-mini-search-preview') } -export function isSupportedResoningEffortModel(model?: Model): boolean { +export function isSupportedReasoningEffortModel(model?: Model): boolean { if (!model) { return false } - if (model.id.includes('claude-3-7-sonnet') || model.id.includes('claude-3.7-sonnet') || isOpenAIoSeries(model)) { + if ( + model.id.includes('claude-3-7-sonnet') || + model.id.includes('claude-3.7-sonnet') || + isOpenAIoSeries(model) || + isGrokReasoningModel(model) + ) { + return true + } + + return false +} + +export function isGrokReasoningModel(model?: Model): boolean { + if (!model) { + return false + } + + if (model.id.includes('grok-3-mini')) { return true } diff --git a/src/renderer/src/i18n/locales/en-us.json b/src/renderer/src/i18n/locales/en-us.json index bcd980da..ad886b8c 100644 --- a/src/renderer/src/i18n/locales/en-us.json +++ b/src/renderer/src/i18n/locales/en-us.json @@ -59,7 +59,7 @@ "settings.reasoning_effort.low": "low", "settings.reasoning_effort.medium": "medium", "settings.reasoning_effort.off": "off", - "settings.reasoning_effort.tip": "Only supports OpenAI o-series and Anthropic reasoning models", + "settings.reasoning_effort.tip": "Only supported by OpenAI o-series, Anthropic, and Grok reasoning models", "settings.more": "Assistant Settings" }, "auth": { diff --git a/src/renderer/src/i18n/locales/ja-jp.json b/src/renderer/src/i18n/locales/ja-jp.json index d1a39138..bab44d01 100644 --- a/src/renderer/src/i18n/locales/ja-jp.json +++ b/src/renderer/src/i18n/locales/ja-jp.json @@ -59,7 +59,7 @@ "settings.reasoning_effort.low": "短い", "settings.reasoning_effort.medium": "中程度", "settings.reasoning_effort.off": "オフ", - "settings.reasoning_effort.tip": "OpenAIのoシリーズとAnthropicの推論モデルのみサポートしています", + "settings.reasoning_effort.tip": "OpenAI o-series、Anthropic、および Grok の推論モデルのみサポート", "settings.more": "アシスタント設定" }, "auth": { diff --git a/src/renderer/src/i18n/locales/ru-ru.json b/src/renderer/src/i18n/locales/ru-ru.json index c07c0c81..6af1f480 100644 --- a/src/renderer/src/i18n/locales/ru-ru.json +++ b/src/renderer/src/i18n/locales/ru-ru.json @@ -59,7 +59,7 @@ "settings.reasoning_effort.low": "Короткая", "settings.reasoning_effort.medium": "Средняя", "settings.reasoning_effort.off": "Выключено", - "settings.reasoning_effort.tip": "Поддерживается только моделями с рассуждением OpenAI o-series и Anthropic", + "settings.reasoning_effort.tip": "Поддерживается только моделями рассуждений OpenAI o-series, Anthropic и Grok", "settings.more": "Настройки ассистента" }, "auth": { diff --git a/src/renderer/src/i18n/locales/zh-cn.json b/src/renderer/src/i18n/locales/zh-cn.json index 43359bf9..8bf5b619 100644 --- a/src/renderer/src/i18n/locales/zh-cn.json +++ b/src/renderer/src/i18n/locales/zh-cn.json @@ -59,7 +59,7 @@ "settings.reasoning_effort.low": "短", "settings.reasoning_effort.medium": "中", "settings.reasoning_effort.off": "关", - "settings.reasoning_effort.tip": "仅支持 OpenAI o-series 和 Anthropic 推理模型", + "settings.reasoning_effort.tip": "仅支持 OpenAI o-series、Anthropic、Grok 推理模型", "settings.more": "助手设置" }, "auth": { diff --git a/src/renderer/src/i18n/locales/zh-tw.json b/src/renderer/src/i18n/locales/zh-tw.json index 41a25f78..fa2fcb0a 100644 --- a/src/renderer/src/i18n/locales/zh-tw.json +++ b/src/renderer/src/i18n/locales/zh-tw.json @@ -59,7 +59,7 @@ "settings.reasoning_effort.low": "短", "settings.reasoning_effort.medium": "中", "settings.reasoning_effort.off": "關", - "settings.reasoning_effort.tip": "僅支援 OpenAI o-series 和 Anthropic 推理模型", + "settings.reasoning_effort.tip": "僅支援 OpenAI o-series、Anthropic 和 Grok 推理模型", "settings.more": "助手設定" }, "auth": { diff --git a/src/renderer/src/pages/home/Tabs/SettingsTab.tsx b/src/renderer/src/pages/home/Tabs/SettingsTab.tsx index a46be2d0..3aad779d 100644 --- a/src/renderer/src/pages/home/Tabs/SettingsTab.tsx +++ b/src/renderer/src/pages/home/Tabs/SettingsTab.tsx @@ -8,7 +8,7 @@ import { isMac, isWindows } from '@renderer/config/constant' -import { isSupportedResoningEffortModel } from '@renderer/config/models' +import { isGrokReasoningModel, isSupportedReasoningEffortModel } from '@renderer/config/models' import { codeThemes } from '@renderer/context/SyntaxHighlighterProvider' import { useAssistant } from '@renderer/hooks/useAssistant' import { useSettings } from '@renderer/hooks/useSettings' @@ -146,7 +146,21 @@ const SettingsTab: FC = (props) => { setMaxTokens(assistant?.settings?.maxTokens ?? DEFAULT_MAX_TOKENS) setStreamOutput(assistant?.settings?.streamOutput ?? true) setReasoningEffort(assistant?.settings?.reasoning_effort) - }, [assistant]) + + // 当是Grok模型时,处理reasoning_effort的设置 + // For Grok models, only 'low' and 'high' reasoning efforts are supported. + // This ensures compatibility with the model's capabilities and avoids unsupported configurations. + if (isGrokReasoningModel(assistant?.model || getDefaultModel())) { + const currentEffort = assistant?.settings?.reasoning_effort + if (!currentEffort || currentEffort === 'low') { + setReasoningEffort('low') // Default to 'low' if no effort is set or if it's already 'low'. + onReasoningEffortChange('low') + } else if (currentEffort === 'medium' || currentEffort === 'high') { + setReasoningEffort('high') // Force 'high' for 'medium' or 'high' to simplify the configuration. + onReasoningEffortChange('high') + } + } + }, [assistant, onReasoningEffortChange]) const formatSliderTooltip = (value?: number) => { if (value === undefined) return '' @@ -263,7 +277,7 @@ const SettingsTab: FC = (props) => { )} - {isSupportedResoningEffortModel(assistant?.model || getDefaultModel()) && ( + {isSupportedReasoningEffortModel(assistant?.model || getDefaultModel()) && ( <> @@ -282,12 +296,19 @@ const SettingsTab: FC = (props) => { setReasoningEffort(typedValue) onReasoningEffortChange(typedValue) }} - options={[ - { value: 'low', label: t('assistants.settings.reasoning_effort.low') }, - { value: 'medium', label: t('assistants.settings.reasoning_effort.medium') }, - { value: 'high', label: t('assistants.settings.reasoning_effort.high') }, - { value: 'off', label: t('assistants.settings.reasoning_effort.off') } - ]} + options={ + isGrokReasoningModel(assistant?.model || getDefaultModel()) + ? [ + { value: 'low', label: t('assistants.settings.reasoning_effort.low') }, + { value: 'high', label: t('assistants.settings.reasoning_effort.high') } + ] + : [ + { value: 'low', label: t('assistants.settings.reasoning_effort.low') }, + { value: 'medium', label: t('assistants.settings.reasoning_effort.medium') }, + { value: 'high', label: t('assistants.settings.reasoning_effort.high') }, + { value: 'off', label: t('assistants.settings.reasoning_effort.off') } + ] + } name="group" block /> diff --git a/src/renderer/src/providers/AiProvider/OpenAIProvider.ts b/src/renderer/src/providers/AiProvider/OpenAIProvider.ts index 1ece14e9..96469470 100644 --- a/src/renderer/src/providers/AiProvider/OpenAIProvider.ts +++ b/src/renderer/src/providers/AiProvider/OpenAIProvider.ts @@ -1,6 +1,7 @@ import { DEFAULT_MAX_TOKENS } from '@renderer/config/constant' import { getOpenAIWebSearchParams, + isGrokReasoningModel, isHunyuanSearchModel, isOpenAIoSeries, isOpenAIWebSearch, @@ -243,6 +244,12 @@ export default class OpenAIProvider extends BaseProvider { } } + if (isGrokReasoningModel(model)) { + return { + reasoning_effort: assistant?.settings?.reasoning_effort + } + } + if (isOpenAIoSeries(model)) { return { reasoning_effort: assistant?.settings?.reasoning_effort