From deb486357ef91dd93cfa3b13f5962a45dc3847f0 Mon Sep 17 00:00:00 2001 From: Camol Date: Sat, 10 May 2025 19:55:56 +0800 Subject: [PATCH] fix: update selectedTypes logic in ModelEditContent for better handling (#5819) refactor: improve model type checking logic in models.ts and ModelEditContent.tsx * Refactor isFunctionCallingModel, isEmbeddingModel, isVisionModel, isReasoningModel, and isWebSearchModel functions for better readability and maintainability. * Simplify type selection logic in ModelEditContent by directly using model.type or defaultTypes. * Remove unnecessary conditional checks to streamline the code. Co-authored-by: kanweiwei --- src/renderer/src/config/models.ts | 244 +++++++++--------- .../ProviderSettings/ModelEditContent.tsx | 17 +- 2 files changed, 132 insertions(+), 129 deletions(-) diff --git a/src/renderer/src/config/models.ts b/src/renderer/src/config/models.ts index 65ed25a04f..d86f1430af 100644 --- a/src/renderer/src/config/models.ts +++ b/src/renderer/src/config/models.ts @@ -237,23 +237,24 @@ export const CLAUDE_SUPPORTED_WEBSEARCH_REGEX = new RegExp( ) export function isFunctionCallingModel(model: Model): boolean { - if (model.type?.includes('function_calling')) { - return true - } + if (!model) return false + if (model.type) { + return model.type.includes('function_calling') + } else { + if (isEmbeddingModel(model)) { + return false + } - if (isEmbeddingModel(model)) { - return false - } + if (model.provider === 'qiniu') { + return ['deepseek-v3-tool', 'deepseek-v3-0324', 'qwq-32b', 'qwen2.5-72b-instruct'].includes(model.id) + } - if (model.provider === 'qiniu') { - return ['deepseek-v3-tool', 'deepseek-v3-0324', 'qwq-32b', 'qwen2.5-72b-instruct'].includes(model.id) - } + if (['deepseek', 'anthropic'].includes(model.provider)) { + return true + } - if (['deepseek', 'anthropic'].includes(model.provider)) { - return true + return FUNCTION_CALLING_REGEX.test(model.id) } - - return FUNCTION_CALLING_REGEX.test(model.id) } export function getModelLogo(modelId: string) { @@ -2188,20 +2189,23 @@ export function isEmbeddingModel(model: Model): boolean { if (!model) { return false } + if (model.type) { + return model.type.includes('embedding') + } else { + if (['anthropic'].includes(model?.provider)) { + return false + } - if (['anthropic'].includes(model?.provider)) { - return false + if (model.provider === 'doubao') { + return EMBEDDING_REGEX.test(model.name) + } + + if (isRerankModel(model)) { + return false + } + + return EMBEDDING_REGEX.test(model.id) } - - if (model.provider === 'doubao') { - return EMBEDDING_REGEX.test(model.name) - } - - if (isRerankModel(model)) { - return false - } - - return EMBEDDING_REGEX.test(model.id) || model.type?.includes('embedding') || false } export function isRerankModel(model: Model): boolean { @@ -2212,16 +2216,20 @@ export function isVisionModel(model: Model): boolean { if (!model) { return false } - // 新添字段 copilot-vision-request 后可使用 vision - // if (model.provider === 'copilot') { - // return false - // } + if (model.type) { + return model.type.includes('vision') + } else { + // 新添字段 copilot-vision-request 后可使用 vision + // if (model.provider === 'copilot') { + // return false + // } - if (model.provider === 'doubao') { - return VISION_REGEX.test(model.name) || model.type?.includes('vision') || false + if (model.provider === 'doubao') { + return VISION_REGEX.test(model.name) + } + + return VISION_REGEX.test(model.id) } - - return VISION_REGEX.test(model.id) || model.type?.includes('vision') || false } export function isOpenAIReasoningModel(model: Model): boolean { @@ -2355,23 +2363,26 @@ export function isReasoningModel(model?: Model): boolean { if (!model) { return false } + if (model.type) { + return model.type.includes('reasoning') + } else { + if (model.provider === 'doubao') { + return REASONING_REGEX.test(model.name) + } - if (model.provider === 'doubao') { - return REASONING_REGEX.test(model.name) || model.type?.includes('reasoning') || false + if ( + isClaudeReasoningModel(model) || + isOpenAIReasoningModel(model) || + isGeminiReasoningModel(model) || + isQwenReasoningModel(model) || + isGrokReasoningModel(model) || + model.id.includes('glm-z1') + ) { + return true + } + + return REASONING_REGEX.test(model.id) } - - if ( - isClaudeReasoningModel(model) || - isOpenAIReasoningModel(model) || - isGeminiReasoningModel(model) || - isQwenReasoningModel(model) || - isGrokReasoningModel(model) || - model.id.includes('glm-z1') - ) { - return true - } - - return REASONING_REGEX.test(model.id) || model.type?.includes('reasoning') || false } export function isSupportedModel(model: OpenAI.Models.Model): boolean { @@ -2386,89 +2397,86 @@ export function isWebSearchModel(model: Model): boolean { if (!model) { return false } - if (model.type) { - if (model.type.includes('web_search')) { - return true + return model.type.includes('web_search') + } else { + const provider = getProviderByModel(model) + + if (!provider) { + return false } - } - const provider = getProviderByModel(model) + const isEmbedding = isEmbeddingModel(model) - if (!provider) { - return false - } + if (isEmbedding) { + return false + } - const isEmbedding = isEmbeddingModel(model) + if (model.id.includes('claude')) { + return CLAUDE_SUPPORTED_WEBSEARCH_REGEX.test(model.id) + } - if (isEmbedding) { - return false - } + if (provider.type === 'openai') { + if ( + isOpenAILLMModel(model) && + !isTextToImageModel(model) && + !isOpenAIReasoningModel(model) && + !GENERATE_IMAGE_MODELS.includes(model.id) + ) { + return true + } - if (model.id.includes('claude')) { - return CLAUDE_SUPPORTED_WEBSEARCH_REGEX.test(model.id) - } + return false + } - if (provider.type === 'openai') { - if ( - isOpenAILLMModel(model) && - !isTextToImageModel(model) && - !isOpenAIReasoningModel(model) && - !GENERATE_IMAGE_MODELS.includes(model.id) - ) { + if (provider.id === 'perplexity') { + return PERPLEXITY_SEARCH_MODELS.includes(model?.id) + } + + if (provider.id === 'aihubmix') { + if ( + isOpenAILLMModel(model) && + !isTextToImageModel(model) && + !isOpenAIReasoningModel(model) && + !GENERATE_IMAGE_MODELS.includes(model.id) + ) { + return true + } + + const models = ['gemini-2.0-flash-search', 'gemini-2.0-flash-exp-search', 'gemini-2.0-pro-exp-02-05-search'] + return models.includes(model?.id) + } + + if (provider?.type === 'openai-compatible') { + if (GEMINI_SEARCH_MODELS.includes(model?.id) || isOpenAIWebSearch(model)) { + return true + } + } + + if (provider.id === 'gemini' || provider?.type === 'gemini') { + return GEMINI_SEARCH_MODELS.includes(model?.id) + } + + if (provider.id === 'hunyuan') { + return model?.id !== 'hunyuan-lite' + } + + if (provider.id === 'zhipu') { + return model?.id?.startsWith('glm-4-') + } + + if (provider.id === 'dashscope') { + const models = ['qwen-turbo', 'qwen-max', 'qwen-plus', 'qwq'] + // matches id like qwen-max-0919, qwen-max-latest + return models.some((i) => model.id.startsWith(i)) + } + + if (provider.id === 'openrouter') { return true } return false } - - if (provider.id === 'perplexity') { - return PERPLEXITY_SEARCH_MODELS.includes(model?.id) - } - - if (provider.id === 'aihubmix') { - if ( - isOpenAILLMModel(model) && - !isTextToImageModel(model) && - !isOpenAIReasoningModel(model) && - !GENERATE_IMAGE_MODELS.includes(model.id) - ) { - return true - } - - const models = ['gemini-2.0-flash-search', 'gemini-2.0-flash-exp-search', 'gemini-2.0-pro-exp-02-05-search'] - return models.includes(model?.id) - } - - if (provider?.type === 'openai-compatible') { - if (GEMINI_SEARCH_MODELS.includes(model?.id) || isOpenAIWebSearch(model)) { - return true - } - } - - if (provider.id === 'gemini' || provider?.type === 'gemini') { - return GEMINI_SEARCH_MODELS.includes(model?.id) - } - - if (provider.id === 'hunyuan') { - return model?.id !== 'hunyuan-lite' - } - - if (provider.id === 'zhipu') { - return model?.id?.startsWith('glm-4-') - } - - if (provider.id === 'dashscope') { - const models = ['qwen-turbo', 'qwen-max', 'qwen-plus', 'qwq'] - // matches id like qwen-max-0919, qwen-max-latest - return models.some((i) => model.id.startsWith(i)) - } - - if (provider.id === 'openrouter') { - return true - } - - return false } export function isGenerateImageModel(model: Model): boolean { diff --git a/src/renderer/src/pages/settings/ProviderSettings/ModelEditContent.tsx b/src/renderer/src/pages/settings/ProviderSettings/ModelEditContent.tsx index 034455c745..3a2759475f 100644 --- a/src/renderer/src/pages/settings/ProviderSettings/ModelEditContent.tsx +++ b/src/renderer/src/pages/settings/ProviderSettings/ModelEditContent.tsx @@ -132,7 +132,7 @@ const ModelEditContent: FC = ({ model, onUpdateModel, ope ] as ModelType[] // 合并现有选择和默认类型 - const selectedTypes = [...new Set([...(model.type || []), ...defaultTypes])] + const selectedTypes = model.type ? model.type : defaultTypes const showTypeConfirmModal = (type: string) => { window.modal.confirm({ @@ -165,28 +165,23 @@ const ModelEditContent: FC = ({ model, onUpdateModel, ope options={[ { label: t('models.type.vision'), - value: 'vision', - disabled: isVisionModel(model) && !selectedTypes.includes('vision') + value: 'vision' }, { label: t('models.type.websearch'), - value: 'web_search', - disabled: isWebSearchModel(model) && !selectedTypes.includes('web_search') + value: 'web_search' }, { label: t('models.type.embedding'), - value: 'embedding', - disabled: isEmbeddingModel(model) && !selectedTypes.includes('embedding') + value: 'embedding' }, { label: t('models.type.reasoning'), - value: 'reasoning', - disabled: isReasoningModel(model) && !selectedTypes.includes('reasoning') + value: 'reasoning' }, { label: t('models.type.function_calling'), - value: 'function_calling', - disabled: isFunctionCallingModel(model) && !selectedTypes.includes('function_calling') + value: 'function_calling' } ]} />