feat: reasoning effort cache (#9357)

* feat(useAssistant): 修改模型切换时推理努力值回退逻辑

当模型切换时,确保推理努力值回退到模型支持的第一个有效值,并默认开启思考模式。使用useRef优化设置引用,避免不必要的依赖。

* feat(assistant): 添加 reasoning_effort_cache 以保留思考模型设置

当从非思考模型切换回思考模型时,恢复上次使用的 reasoning_effort 值

* fix(assistant): 修复思考模式切换时缓存未正确更新的问题

* fix(useAssistant): 修复模型选项回退逻辑以支持推理模式

当启用推理模式时,回退到支持推理的选项,否则回退到默认选项

* docs(types): 完善 AssistantSettings 类型注释中的 TODO 说明
This commit is contained in:
Phantom 2025-08-21 14:18:19 +08:00 committed by GitHub
parent 062b3b0a33
commit ea6a1752e7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 46 additions and 12 deletions

View File

@ -3,7 +3,8 @@ import {
getThinkModelType,
isSupportedReasoningEffortModel,
isSupportedThinkingTokenModel,
MODEL_SUPPORTED_OPTIONS
MODEL_SUPPORTED_OPTIONS,
MODEL_SUPPORTED_REASONING_EFFORT
} from '@renderer/config/models'
import { db } from '@renderer/databases'
import { getDefaultTopic } from '@renderer/services/AssistantService'
@ -24,9 +25,9 @@ import {
updateTopics
} from '@renderer/store/assistants'
import { setDefaultModel, setQuickModel, setTranslateModel } from '@renderer/store/llm'
import { Assistant, AssistantSettings, Model, Topic } from '@renderer/types'
import { Assistant, AssistantSettings, Model, ThinkingOption, Topic } from '@renderer/types'
import { uuid } from '@renderer/utils'
import { useCallback, useEffect, useMemo } from 'react'
import { useCallback, useEffect, useMemo, useRef } from 'react'
import { useTranslation } from 'react-i18next'
import { TopicManager } from './useTopic'
@ -84,6 +85,12 @@ export function useAssistant(id: string) {
const assistantWithModel = useMemo(() => ({ ...assistant, model }), [assistant, model])
const settingsRef = useRef(assistant?.settings)
useEffect(() => {
settingsRef.current = assistant.settings
}, [assistant?.settings])
const updateAssistantSettings = useCallback(
(settings: Partial<AssistantSettings>) => {
assistant?.id && dispatch(_updateAssistantSettings({ assistantId: assistant.id, settings }))
@ -93,28 +100,46 @@ export function useAssistant(id: string) {
// 当model变化时同步reasoning effort为模型支持的合法值
useEffect(() => {
if (assistant?.settings) {
const settings = settingsRef.current
if (settings) {
const currentReasoningEffort = settings.reasoning_effort
if (isSupportedThinkingTokenModel(model) || isSupportedReasoningEffortModel(model)) {
const currentReasoningEffort = assistant?.settings?.reasoning_effort
const supportedOptions = MODEL_SUPPORTED_OPTIONS[getThinkModelType(model)]
if (currentReasoningEffort && !supportedOptions.includes(currentReasoningEffort)) {
// 选项不支持时,回退到第一个支持的值
// 注意这里假设可用的options不会为空
const fallbackOption = supportedOptions[0]
const modelType = getThinkModelType(model)
const supportedOptions = MODEL_SUPPORTED_OPTIONS[modelType]
if (supportedOptions.every((option) => option !== currentReasoningEffort)) {
const cache = settings.reasoning_effort_cache
let fallbackOption: ThinkingOption
// 选项不支持时,首先尝试恢复到上次使用的值
if (cache && supportedOptions.includes(cache)) {
fallbackOption = cache
} else {
// 灵活回退到支持的值
// 注意这里假设可用的options不会为空
const enableThinking = currentReasoningEffort !== undefined
fallbackOption = enableThinking
? MODEL_SUPPORTED_REASONING_EFFORT[modelType][0]
: MODEL_SUPPORTED_OPTIONS[modelType][0]
}
updateAssistantSettings({
reasoning_effort: fallbackOption === 'off' ? undefined : fallbackOption,
qwenThinkMode: fallbackOption === 'off'
reasoning_effort_cache: fallbackOption === 'off' ? undefined : fallbackOption,
qwenThinkMode: fallbackOption === 'off' ? undefined : true
})
} else {
// 对于支持的选项, 不再更新 cache.
}
} else {
// 切换到非思考模型时保留cache
updateAssistantSettings({
reasoning_effort: undefined,
reasoning_effort_cache: currentReasoningEffort,
qwenThinkMode: undefined
})
}
}
}, [assistant?.settings, model, updateAssistantSettings])
}, [model, updateAssistantSettings])
return {
assistant: assistantWithModel,

View File

@ -77,12 +77,14 @@ const ThinkingButton: FC<Props> = ({ ref, model, assistant, ToolbarButton }): Re
if (!isEnabled) {
updateAssistantSettings({
reasoning_effort: undefined,
reasoning_effort_cache: undefined,
qwenThinkMode: false
})
return
}
updateAssistantSettings({
reasoning_effort: option,
reasoning_effort_cache: option,
qwenThinkMode: true
})
return

View File

@ -99,6 +99,13 @@ export type AssistantSettings = {
defaultModel?: Model
customParameters?: AssistantSettingCustomParameters[]
reasoning_effort?: ReasoningEffortOption
/** 使 reasoning effort, .
*
* TODO: 目前 reasoning_effort === undefined
* / cache
*
*/
reasoning_effort_cache?: ReasoningEffortOption
qwenThinkMode?: boolean
toolUseMode: 'function' | 'prompt'
}