From 536aa68389ea10d363e35ce8dc5d965a19566d01 Mon Sep 17 00:00:00 2001 From: lihqi Date: Mon, 28 Jul 2025 21:27:31 +0800 Subject: [PATCH] feat: add Top-P parameter toggle with default enabled state and improved UI styling (#8137) * feat: add Top-P parameter toggle with default enabled state and improved UI styling * fix: resolve undefined enableTopP issue in ppio models by using getAssistantSettings * refactor(api): Unify getTopP method to BaseApiClient * feat(settings): adjust layout of Top-P setting in assistant model settings * feat: add temperature parameter toggle control with UI and multi-language support * fix: Fix lint error * fix: Sort these imports * style(settings): refactor model settings layout and styles * chore: yarn sync:i18n --- .../src/aiCore/clients/BaseApiClient.ts | 13 +- .../clients/anthropic/AnthropicAPIClient.ts | 4 +- .../aiCore/clients/openai/OpenAIBaseClient.ts | 15 +- src/renderer/src/i18n/locales/zh-cn.json | 2 +- .../src/pages/home/Tabs/SettingsTab.tsx | 39 ++-- .../AssistantModelSettings.tsx | 167 ++++++++++-------- .../DefaultAssistantSettings.tsx | 156 +++++++++------- src/renderer/src/services/AssistantService.ts | 6 + src/renderer/src/types/index.ts | 8 +- 9 files changed, 246 insertions(+), 164 deletions(-) diff --git a/src/renderer/src/aiCore/clients/BaseApiClient.ts b/src/renderer/src/aiCore/clients/BaseApiClient.ts index 576381c875..9bb0f92789 100644 --- a/src/renderer/src/aiCore/clients/BaseApiClient.ts +++ b/src/renderer/src/aiCore/clients/BaseApiClient.ts @@ -8,6 +8,7 @@ import { import { REFERENCE_PROMPT } from '@renderer/config/prompts' import { getLMStudioKeepAliveTime } from '@renderer/hooks/useLMStudio' import { getStoreSetting } from '@renderer/hooks/useSettings' +import { getAssistantSettings } from '@renderer/services/AssistantService' import { SettingsState } from '@renderer/store/settings' import { Assistant, @@ -185,11 +186,19 @@ export abstract class BaseApiClient< } public getTemperature(assistant: Assistant, model: Model): number | undefined { - return isNotSupportTemperatureAndTopP(model) ? undefined : assistant.settings?.temperature + if (isNotSupportTemperatureAndTopP(model)) { + return undefined + } + const assistantSettings = getAssistantSettings(assistant) + return assistantSettings?.enableTemperature ? assistantSettings?.temperature : undefined } public getTopP(assistant: Assistant, model: Model): number | undefined { - return isNotSupportTemperatureAndTopP(model) ? undefined : assistant.settings?.topP + if (isNotSupportTemperatureAndTopP(model)) { + return undefined + } + const assistantSettings = getAssistantSettings(assistant) + return assistantSettings?.enableTopP ? assistantSettings?.topP : undefined } protected getServiceTier(model: Model) { diff --git a/src/renderer/src/aiCore/clients/anthropic/AnthropicAPIClient.ts b/src/renderer/src/aiCore/clients/anthropic/AnthropicAPIClient.ts index ae34a94d5c..6a73bf47ce 100644 --- a/src/renderer/src/aiCore/clients/anthropic/AnthropicAPIClient.ts +++ b/src/renderer/src/aiCore/clients/anthropic/AnthropicAPIClient.ts @@ -138,14 +138,14 @@ export class AnthropicAPIClient extends BaseApiClient< if (assistant.settings?.reasoning_effort && isClaudeReasoningModel(model)) { return undefined } - return assistant.settings?.temperature + return super.getTemperature(assistant, model) } override getTopP(assistant: Assistant, model: Model): number | undefined { if (assistant.settings?.reasoning_effort && isClaudeReasoningModel(model)) { return undefined } - return assistant.settings?.topP + return super.getTopP(assistant, model) } /** diff --git a/src/renderer/src/aiCore/clients/openai/OpenAIBaseClient.ts b/src/renderer/src/aiCore/clients/openai/OpenAIBaseClient.ts index 144dea130c..9e4042fa3c 100644 --- a/src/renderer/src/aiCore/clients/openai/OpenAIBaseClient.ts +++ b/src/renderer/src/aiCore/clients/openai/OpenAIBaseClient.ts @@ -1,7 +1,6 @@ import { loggerService } from '@logger' import { isClaudeReasoningModel, - isNotSupportTemperatureAndTopP, isOpenAIReasoningModel, isSupportedModel, isSupportedReasoningEffortOpenAIModel @@ -172,23 +171,17 @@ export abstract class OpenAIBaseClient< } override getTemperature(assistant: Assistant, model: Model): number | undefined { - if ( - isNotSupportTemperatureAndTopP(model) || - (assistant.settings?.reasoning_effort && isClaudeReasoningModel(model)) - ) { + if (assistant.settings?.reasoning_effort && isClaudeReasoningModel(model)) { return undefined } - return assistant.settings?.temperature + return super.getTemperature(assistant, model) } override getTopP(assistant: Assistant, model: Model): number | undefined { - if ( - isNotSupportTemperatureAndTopP(model) || - (assistant.settings?.reasoning_effort && isClaudeReasoningModel(model)) - ) { + if (assistant.settings?.reasoning_effort && isClaudeReasoningModel(model)) { return undefined } - return assistant.settings?.topP + return super.getTopP(assistant, model) } /** diff --git a/src/renderer/src/i18n/locales/zh-cn.json b/src/renderer/src/i18n/locales/zh-cn.json index 8f5fb1e073..30bc78ebb0 100644 --- a/src/renderer/src/i18n/locales/zh-cn.json +++ b/src/renderer/src/i18n/locales/zh-cn.json @@ -465,7 +465,7 @@ }, "top_p": { "label": "Top-P", - "tip": "默认值为 1,值越小,AI 生成的内容越单调,也越容易理解;值越大,AI 回复的词汇围越大,越多样化" + "tip": "默认值为 1,值越小,AI 生成的内容越单调,也越容易理解;值越大,AI 回复的词汇范围越大,越多样化" } }, "suggestions": { diff --git a/src/renderer/src/pages/home/Tabs/SettingsTab.tsx b/src/renderer/src/pages/home/Tabs/SettingsTab.tsx index 317e3f7edf..7f0d91602c 100644 --- a/src/renderer/src/pages/home/Tabs/SettingsTab.tsx +++ b/src/renderer/src/pages/home/Tabs/SettingsTab.tsx @@ -68,6 +68,7 @@ const SettingsTab: FC = (props) => { const { themeNames } = useCodeStyle() const [temperature, setTemperature] = useState(assistant?.settings?.temperature ?? DEFAULT_TEMPERATURE) + const [enableTemperature, setEnableTemperature] = useState(assistant?.settings?.enableTemperature ?? true) const [contextCount, setContextCount] = useState(assistant?.settings?.contextCount ?? DEFAULT_CONTEXTCOUNT) const [enableMaxTokens, setEnableMaxTokens] = useState(assistant?.settings?.enableMaxTokens ?? false) const [maxTokens, setMaxTokens] = useState(assistant?.settings?.maxTokens ?? 0) @@ -154,6 +155,7 @@ const SettingsTab: FC = (props) => { useEffect(() => { setTemperature(assistant?.settings?.temperature ?? DEFAULT_TEMPERATURE) + setEnableTemperature(assistant?.settings?.enableTemperature ?? true) setContextCount(assistant?.settings?.contextCount ?? DEFAULT_CONTEXTCOUNT) setEnableMaxTokens(assistant?.settings?.enableMaxTokens ?? false) setMaxTokens(assistant?.settings?.maxTokens ?? DEFAULT_MAX_TOKENS) @@ -193,19 +195,32 @@ const SettingsTab: FC = (props) => { + { + setEnableTemperature(enabled) + onUpdateAssistantSettings({ enableTemperature: enabled }) + }} + /> - - - - - + {enableTemperature ? ( + + + + + + ) : ( + + )} {t('chat.settings.context_count.label')} diff --git a/src/renderer/src/pages/settings/AssistantSettings/AssistantModelSettings.tsx b/src/renderer/src/pages/settings/AssistantSettings/AssistantModelSettings.tsx index 0e16d855df..574fa86fc8 100644 --- a/src/renderer/src/pages/settings/AssistantSettings/AssistantModelSettings.tsx +++ b/src/renderer/src/pages/settings/AssistantSettings/AssistantModelSettings.tsx @@ -29,9 +29,11 @@ const AssistantModelSettings: FC = ({ assistant, updateAssistant, updateA const [toolUseMode, setToolUseMode] = useState(assistant?.settings?.toolUseMode ?? 'prompt') const [defaultModel, setDefaultModel] = useState(assistant?.defaultModel) const [topP, setTopP] = useState(assistant?.settings?.topP ?? 1) + const [enableTopP, setEnableTopP] = useState(assistant?.settings?.enableTopP ?? true) const [customParameters, setCustomParameters] = useState( assistant?.settings?.customParameters ?? [] ) + const [enableTemperature, setEnableTemperature] = useState(assistant?.settings?.enableTemperature ?? true) const customParametersRef = useRef(customParameters) @@ -151,20 +153,24 @@ const AssistantModelSettings: FC = ({ assistant, updateAssistant, updateA const onReset = () => { setTemperature(DEFAULT_TEMPERATURE) + setEnableTemperature(true) setContextCount(DEFAULT_CONTEXTCOUNT) setEnableMaxTokens(false) setMaxTokens(0) setStreamOutput(true) setTopP(1) + setEnableTopP(true) setCustomParameters([]) setToolUseMode('prompt') updateAssistantSettings({ temperature: DEFAULT_TEMPERATURE, + enableTemperature: true, contextCount: DEFAULT_CONTEXTCOUNT, enableMaxTokens: false, maxTokens: 0, streamOutput: true, topP: 1, + enableTopP: true, customParameters: [], toolUseMode: 'prompt' }) @@ -226,86 +232,103 @@ const AssistantModelSettings: FC = ({ assistant, updateAssistant, updateA - - + + + - - - { - if (value !== null) { - setTemperature(value) - setTimeout(() => updateAssistantSettings({ temperature: value }), 500) - } - }} - style={{ width: '100%' }} - /> - - - - - - - + + { + setEnableTemperature(enabled) + updateAssistantSettings({ enableTemperature: enabled }) + }} + /> + + {enableTemperature && ( + + + + + + { + if (!isNull(value)) { + setTemperature(value) + setTimeout(() => updateAssistantSettings({ temperature: value }), 500) + } + }} + style={{ width: '100%' }} + /> + + + )} - - - - - - { - if (!isNull(value)) { - setTopP(value) - setTimeout(() => updateAssistantSettings({ topP: value }), 500) - } - }} - style={{ width: '100%' }} - /> - - - - - - - + + + + + + + + { + setEnableTopP(enabled) + updateAssistantSettings({ enableTopP: enabled }) + }} + /> + + {enableTopP && ( + + + + + + { + if (!isNull(value)) { + setTopP(value) + setTimeout(() => updateAssistantSettings({ topP: value }), 500) + } + }} + style={{ width: '100%' }} + /> + + + )} diff --git a/src/renderer/src/pages/settings/ModelSettings/DefaultAssistantSettings.tsx b/src/renderer/src/pages/settings/ModelSettings/DefaultAssistantSettings.tsx index 6f97b9762a..edf96505bd 100644 --- a/src/renderer/src/pages/settings/ModelSettings/DefaultAssistantSettings.tsx +++ b/src/renderer/src/pages/settings/ModelSettings/DefaultAssistantSettings.tsx @@ -13,15 +13,17 @@ import { Dispatch, FC, SetStateAction, useState } from 'react' import { useTranslation } from 'react-i18next' import styled from 'styled-components' -import { SettingContainer, SettingSubtitle } from '..' +import { SettingContainer, SettingRow, SettingSubtitle } from '..' const AssistantSettings: FC = () => { const { defaultAssistant, updateDefaultAssistant } = useDefaultAssistant() const [temperature, setTemperature] = useState(defaultAssistant.settings?.temperature ?? DEFAULT_TEMPERATURE) + const [enableTemperature, setEnableTemperature] = useState(defaultAssistant.settings?.enableTemperature ?? true) const [contextCount, setContextCount] = useState(defaultAssistant.settings?.contextCount ?? DEFAULT_CONTEXTCOUNT) const [enableMaxTokens, setEnableMaxTokens] = useState(defaultAssistant?.settings?.enableMaxTokens ?? false) const [maxTokens, setMaxTokens] = useState(defaultAssistant?.settings?.maxTokens ?? 0) const [topP, setTopP] = useState(defaultAssistant.settings?.topP ?? 1) + const [enableTopP, setEnableTopP] = useState(defaultAssistant.settings?.enableTopP ?? true) const [emoji, setEmoji] = useState(defaultAssistant.emoji || getLeadingEmoji(defaultAssistant.name) || '') const [name, setName] = useState( defaultAssistant.name.replace(getLeadingEmoji(defaultAssistant.name) || '', '').trim() @@ -36,11 +38,13 @@ const AssistantSettings: FC = () => { settings: { ...defaultAssistant.settings, temperature: settings.temperature ?? temperature, + enableTemperature: settings.enableTemperature ?? enableTemperature, contextCount: settings.contextCount ?? contextCount, enableMaxTokens: settings.enableMaxTokens ?? enableMaxTokens, maxTokens: settings.maxTokens ?? maxTokens, streamOutput: settings.streamOutput ?? true, - topP: settings.topP ?? topP + topP: settings.topP ?? topP, + enableTopP: settings.enableTopP ?? enableTopP } }) } @@ -61,20 +65,24 @@ const AssistantSettings: FC = () => { const onReset = () => { setTemperature(DEFAULT_TEMPERATURE) + setEnableTemperature(true) setContextCount(DEFAULT_CONTEXTCOUNT) setEnableMaxTokens(false) setMaxTokens(0) setTopP(1) + setEnableTopP(true) updateDefaultAssistant({ ...defaultAssistant, settings: { ...defaultAssistant.settings, temperature: DEFAULT_TEMPERATURE, + enableTemperature: true, contextCount: DEFAULT_CONTEXTCOUNT, enableMaxTokens: false, maxTokens: DEFAULT_MAX_TOKENS, streamOutput: true, - topP: 1 + topP: 1, + enableTopP: true } }) } @@ -96,9 +104,11 @@ const AssistantSettings: FC = () => { } return ( - + {t('common.name')} - + } arrow> @@ -129,84 +139,108 @@ const AssistantSettings: FC = () => { style={{ flex: 1 }} /> - {t('common.prompt')} + {t('common.prompt')}