mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2025-12-29 14:31:35 +08:00
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:
parent
062b3b0a33
commit
ea6a1752e7
@ -3,7 +3,8 @@ import {
|
|||||||
getThinkModelType,
|
getThinkModelType,
|
||||||
isSupportedReasoningEffortModel,
|
isSupportedReasoningEffortModel,
|
||||||
isSupportedThinkingTokenModel,
|
isSupportedThinkingTokenModel,
|
||||||
MODEL_SUPPORTED_OPTIONS
|
MODEL_SUPPORTED_OPTIONS,
|
||||||
|
MODEL_SUPPORTED_REASONING_EFFORT
|
||||||
} from '@renderer/config/models'
|
} from '@renderer/config/models'
|
||||||
import { db } from '@renderer/databases'
|
import { db } from '@renderer/databases'
|
||||||
import { getDefaultTopic } from '@renderer/services/AssistantService'
|
import { getDefaultTopic } from '@renderer/services/AssistantService'
|
||||||
@ -24,9 +25,9 @@ import {
|
|||||||
updateTopics
|
updateTopics
|
||||||
} from '@renderer/store/assistants'
|
} from '@renderer/store/assistants'
|
||||||
import { setDefaultModel, setQuickModel, setTranslateModel } from '@renderer/store/llm'
|
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 { uuid } from '@renderer/utils'
|
||||||
import { useCallback, useEffect, useMemo } from 'react'
|
import { useCallback, useEffect, useMemo, useRef } from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
|
|
||||||
import { TopicManager } from './useTopic'
|
import { TopicManager } from './useTopic'
|
||||||
@ -84,6 +85,12 @@ export function useAssistant(id: string) {
|
|||||||
|
|
||||||
const assistantWithModel = useMemo(() => ({ ...assistant, model }), [assistant, model])
|
const assistantWithModel = useMemo(() => ({ ...assistant, model }), [assistant, model])
|
||||||
|
|
||||||
|
const settingsRef = useRef(assistant?.settings)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
settingsRef.current = assistant.settings
|
||||||
|
}, [assistant?.settings])
|
||||||
|
|
||||||
const updateAssistantSettings = useCallback(
|
const updateAssistantSettings = useCallback(
|
||||||
(settings: Partial<AssistantSettings>) => {
|
(settings: Partial<AssistantSettings>) => {
|
||||||
assistant?.id && dispatch(_updateAssistantSettings({ assistantId: assistant.id, settings }))
|
assistant?.id && dispatch(_updateAssistantSettings({ assistantId: assistant.id, settings }))
|
||||||
@ -93,28 +100,46 @@ export function useAssistant(id: string) {
|
|||||||
|
|
||||||
// 当model变化时,同步reasoning effort为模型支持的合法值
|
// 当model变化时,同步reasoning effort为模型支持的合法值
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (assistant?.settings) {
|
const settings = settingsRef.current
|
||||||
|
if (settings) {
|
||||||
|
const currentReasoningEffort = settings.reasoning_effort
|
||||||
if (isSupportedThinkingTokenModel(model) || isSupportedReasoningEffortModel(model)) {
|
if (isSupportedThinkingTokenModel(model) || isSupportedReasoningEffortModel(model)) {
|
||||||
const currentReasoningEffort = assistant?.settings?.reasoning_effort
|
const modelType = getThinkModelType(model)
|
||||||
const supportedOptions = MODEL_SUPPORTED_OPTIONS[getThinkModelType(model)]
|
const supportedOptions = MODEL_SUPPORTED_OPTIONS[modelType]
|
||||||
if (currentReasoningEffort && !supportedOptions.includes(currentReasoningEffort)) {
|
if (supportedOptions.every((option) => option !== currentReasoningEffort)) {
|
||||||
// 选项不支持时,回退到第一个支持的值
|
const cache = settings.reasoning_effort_cache
|
||||||
// 注意:这里假设可用的options不会为空
|
let fallbackOption: ThinkingOption
|
||||||
const fallbackOption = supportedOptions[0]
|
|
||||||
|
// 选项不支持时,首先尝试恢复到上次使用的值
|
||||||
|
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({
|
updateAssistantSettings({
|
||||||
reasoning_effort: fallbackOption === 'off' ? undefined : fallbackOption,
|
reasoning_effort: fallbackOption === 'off' ? undefined : fallbackOption,
|
||||||
qwenThinkMode: fallbackOption === 'off'
|
reasoning_effort_cache: fallbackOption === 'off' ? undefined : fallbackOption,
|
||||||
|
qwenThinkMode: fallbackOption === 'off' ? undefined : true
|
||||||
})
|
})
|
||||||
|
} else {
|
||||||
|
// 对于支持的选项, 不再更新 cache.
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
// 切换到非思考模型时保留cache
|
||||||
updateAssistantSettings({
|
updateAssistantSettings({
|
||||||
reasoning_effort: undefined,
|
reasoning_effort: undefined,
|
||||||
|
reasoning_effort_cache: currentReasoningEffort,
|
||||||
qwenThinkMode: undefined
|
qwenThinkMode: undefined
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [assistant?.settings, model, updateAssistantSettings])
|
}, [model, updateAssistantSettings])
|
||||||
|
|
||||||
return {
|
return {
|
||||||
assistant: assistantWithModel,
|
assistant: assistantWithModel,
|
||||||
|
|||||||
@ -77,12 +77,14 @@ const ThinkingButton: FC<Props> = ({ ref, model, assistant, ToolbarButton }): Re
|
|||||||
if (!isEnabled) {
|
if (!isEnabled) {
|
||||||
updateAssistantSettings({
|
updateAssistantSettings({
|
||||||
reasoning_effort: undefined,
|
reasoning_effort: undefined,
|
||||||
|
reasoning_effort_cache: undefined,
|
||||||
qwenThinkMode: false
|
qwenThinkMode: false
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
updateAssistantSettings({
|
updateAssistantSettings({
|
||||||
reasoning_effort: option,
|
reasoning_effort: option,
|
||||||
|
reasoning_effort_cache: option,
|
||||||
qwenThinkMode: true
|
qwenThinkMode: true
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
|
|||||||
@ -99,6 +99,13 @@ export type AssistantSettings = {
|
|||||||
defaultModel?: Model
|
defaultModel?: Model
|
||||||
customParameters?: AssistantSettingCustomParameters[]
|
customParameters?: AssistantSettingCustomParameters[]
|
||||||
reasoning_effort?: ReasoningEffortOption
|
reasoning_effort?: ReasoningEffortOption
|
||||||
|
/** 保留上一次使用思考模型时的 reasoning effort, 在从非思考模型切换到思考模型时恢复.
|
||||||
|
*
|
||||||
|
* TODO: 目前 reasoning_effort === undefined 有两个语义,有的场景是显式关闭思考,有的场景是不传参。
|
||||||
|
* 未来应该重构思考控制,将启用/关闭思考和思考选项分离,这样就不用依赖 cache 了。
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
reasoning_effort_cache?: ReasoningEffortOption
|
||||||
qwenThinkMode?: boolean
|
qwenThinkMode?: boolean
|
||||||
toolUseMode: 'function' | 'prompt'
|
toolUseMode: 'function' | 'prompt'
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user