From 5c383c0634aca63866bae20cf48ec17ebc0718f8 Mon Sep 17 00:00:00 2001 From: duanfuxiang Date: Wed, 18 Jun 2025 07:40:38 +0800 Subject: [PATCH] save user custom input model name --- .../components/ModelProviderSettings.tsx | 97 ++++++++++++------- .../components/ProviderModelsPicker.tsx | 59 ++++++++--- src/types/settings.ts | 72 +++++++++----- 3 files changed, 156 insertions(+), 72 deletions(-) diff --git a/src/settings/components/ModelProviderSettings.tsx b/src/settings/components/ModelProviderSettings.tsx index 1806139..751c536 100644 --- a/src/settings/components/ModelProviderSettings.tsx +++ b/src/settings/components/ModelProviderSettings.tsx @@ -44,7 +44,7 @@ const keyMap: Record = { 'OpenAICompatible': 'openaicompatibleProvider', }; -const getProviderSettingKey = (provider: ApiProvider): ProviderSettingKey => { +export const getProviderSettingKey = (provider: ApiProvider): ProviderSettingKey => { return keyMap[provider]; }; @@ -70,7 +70,7 @@ const CustomProviderSettings: React.FC = ({ plugin, // 获取已设置API Key的提供商列表 const getSettedProviders = (): ApiProvider[] => { - return providers.filter(provider => { + return providers.filter(provider => { const providerSetting = getProviderSetting(provider); return providerSetting.apiKey && providerSetting.apiKey.trim() !== ''; }); @@ -79,7 +79,7 @@ const CustomProviderSettings: React.FC = ({ plugin, // 一键配置模型 const handleOneClickConfig = () => { const settedProviders = getSettedProviders(); - + if (settedProviders.length === 0) { // 提示用户未设置任何key alert(t("settings.ModelProvider.noApiKeySet")); @@ -88,7 +88,7 @@ const CustomProviderSettings: React.FC = ({ plugin, // 选择chat和autocomplete的提供商(按providers排序选择最靠前的) const selectedProvider = providers.find(provider => settedProviders.includes(provider)); - + // 选择embedding的提供商(按embeddingProviders排序选择最靠前的) const embeddingProvider = embeddingProviders.find(provider => settedProviders.includes(provider)); @@ -98,7 +98,7 @@ const CustomProviderSettings: React.FC = ({ plugin, if (selectedProvider) { const defaultModels = GetDefaultModelId(selectedProvider); - + // 设置chat和autocomplete模型 if (defaultModels.chat) { newSettings.chatModelProvider = selectedProvider; @@ -116,7 +116,7 @@ const CustomProviderSettings: React.FC = ({ plugin, if (embeddingProvider) { const embeddingDefaultModels = GetDefaultModelId(embeddingProvider); - + // 设置embedding模型 if (embeddingDefaultModels.embedding) { newSettings.embeddingModelProvider = embeddingProvider; @@ -171,37 +171,37 @@ const CustomProviderSettings: React.FC = ({ plugin, }); }; - const testApiConnection = async (provider: ApiProvider) => { + const testApiConnection = async (provider: ApiProvider, modelId?: string) => { console.log(`Testing connection for ${provider}...`); - + try { // 动态导入LLMManager以避免循环依赖 const { default: LLMManager } = await import('../../core/llm/manager'); const { GetDefaultModelId } = await import('../../utils/api'); - + // 对于Ollama和OpenAICompatible,不支持测试API连接 if (provider === ApiProvider.Ollama || provider === ApiProvider.OpenAICompatible) { throw new Error(t("settings.ModelProvider.testConnection.notSupported", { provider })); } - + // 创建LLM管理器实例 const llmManager = new LLMManager(settings); - + // 获取提供商的默认聊天模型 const defaultModels = GetDefaultModelId(provider); - const testModelId = defaultModels.chat; - + const testModelId = modelId || defaultModels.chat; + // 对于没有默认模型的提供商,使用通用的测试模型 if (!testModelId) { throw new Error(t("settings.ModelProvider.testConnection.noDefaultModel", { provider })); } - + // 构造测试模型对象 const testModel = { provider: provider, modelId: testModelId }; - + // 构造简单的测试请求 const testRequest = { messages: [ @@ -214,11 +214,11 @@ const CustomProviderSettings: React.FC = ({ plugin, max_tokens: 10, temperature: 0 }; - + // 设置超时选项 const abortController = new AbortController(); const timeoutId = setTimeout(() => abortController.abort(), 10000); // 10秒超时 - + try { // 发起API调用测试 const response = await llmManager.generateResponse( @@ -226,9 +226,9 @@ const CustomProviderSettings: React.FC = ({ plugin, testRequest, { signal: abortController.signal } ); - + clearTimeout(timeoutId); - + // 检查响应是否有效 if (response && response.choices && response.choices.length > 0) { console.log(`✅ ${provider} connection test successful:`, response.choices[0]?.message?.content); @@ -241,13 +241,13 @@ const CustomProviderSettings: React.FC = ({ plugin, clearTimeout(timeoutId); throw apiError; } - + } catch (error) { console.error(`❌ ${provider} connection test failed:`, error); - + // 根据错误类型提供更具体的错误信息 let errorMessage = t("settings.ModelProvider.testConnection.connectionFailed"); - + if (error.message?.includes('API key')) { errorMessage = t("settings.ModelProvider.testConnection.invalidApiKey"); } else if (error.message?.includes('base URL') || error.message?.includes('baseURL')) { @@ -285,27 +285,58 @@ const CustomProviderSettings: React.FC = ({ plugin, return settings[providerKey] || {}; }; - const updateChatModelId = (provider: ApiProvider, modelId: string) => { + const updateChatModelId = ( + provider: ApiProvider, + modelId: string, + isCustom: boolean = false + ) => { + console.log(`updateChatModelId: ${provider} -> ${modelId}, isCustom: ${isCustom}`) + const providerSettingKey = getProviderSettingKey(provider); + const providerSettings = settings[providerSettingKey] || {}; + const currentModels = providerSettings.models || new Set(); + handleSettingsUpdate({ ...settings, chatModelProvider: provider, - chatModelId: modelId + chatModelId: modelId, + [providerSettingKey]: { + ...providerSettings, + models: isCustom ? new Set([...currentModels, modelId]) : currentModels + } }); }; - const updateApplyModelId = (provider: ApiProvider, modelId: string) => { + const updateApplyModelId = (provider: ApiProvider, modelId: string, isCustom: boolean = false) => { + console.log(`updateApplyModelId: ${provider} -> ${modelId}, isCustom: ${isCustom}`) + const providerSettingKey = getProviderSettingKey(provider); + const providerSettings = settings[providerSettingKey] || {}; + const currentModels = providerSettings.models || new Set(); + handleSettingsUpdate({ ...settings, applyModelProvider: provider, - applyModelId: modelId + applyModelId: modelId, + [providerSettingKey]: { + ...providerSettings, + models: isCustom ? new Set([...currentModels, modelId]) : currentModels + } }); }; - const updateEmbeddingModelId = (provider: ApiProvider, modelId: string) => { + const updateEmbeddingModelId = (provider: ApiProvider, modelId: string, isCustom: boolean = false) => { + console.log(`updateEmbeddingModelId: ${provider} -> ${modelId}, isCustom: ${isCustom}`) + const providerSettingKey = getProviderSettingKey(provider); + const providerSettings = settings[providerSettingKey] || {}; + const currentModels = providerSettings.models || new Set(); + handleSettingsUpdate({ ...settings, embeddingModelProvider: provider, - embeddingModelId: modelId + embeddingModelId: modelId, + [providerSettingKey]: { + ...providerSettings, + models: isCustom ? new Set([...currentModels, modelId]) : currentModels + } }); }; @@ -313,7 +344,7 @@ const CustomProviderSettings: React.FC = ({ plugin, const generateApiKeyDescription = (provider: ApiProvider): React.ReactNode => { const apiUrl = getProviderApiUrl(provider); const baseDescription = String(t("settings.ApiProvider.enterApiKeyDescription")); - + if (!apiUrl) { // 如果没有URL,直接移除占位符 return baseDescription.replace('{provider_api_url}', ''); @@ -328,9 +359,9 @@ const CustomProviderSettings: React.FC = ({ plugin, return ( <> {parts[0]} - @@ -398,7 +429,7 @@ const CustomProviderSettings: React.FC = ({ plugin,

{t("settings.ModelProvider.modelSelection")}:

-