From 79cabadfb8b2acb8ef7435658b650e5d5a618c82 Mon Sep 17 00:00:00 2001 From: kangfenmao Date: Sat, 9 Nov 2024 23:11:25 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E5=8A=A0=E5=85=A5=E8=B4=A6=E5=8F=B7?= =?UTF-8?q?=E8=BD=AE=E8=AF=A2=E5=8A=9F=E8=83=BD=20#293?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/renderer/src/i18n/locales/en-us.json | 1 + src/renderer/src/i18n/locales/zh-cn.json | 1 + src/renderer/src/i18n/locales/zh-tw.json | 1 + .../ProviderSettings/ProviderSetting.tsx | 5 ++-- .../src/providers/AnthropicProvider.ts | 2 +- src/renderer/src/providers/BaseProvider.ts | 26 ++++++++++++++++++- src/renderer/src/providers/GeminiProvider.ts | 4 +-- src/renderer/src/providers/OpenAIProvider.ts | 5 ++-- src/renderer/src/services/ApiService.ts | 5 ++-- 9 files changed, 40 insertions(+), 10 deletions(-) diff --git a/src/renderer/src/i18n/locales/en-us.json b/src/renderer/src/i18n/locales/en-us.json index 51f2bf06..8e784f29 100644 --- a/src/renderer/src/i18n/locales/en-us.json +++ b/src/renderer/src/i18n/locales/en-us.json @@ -289,6 +289,7 @@ "advanced.title": "Advanced Settings", "advanced.click_assistant_switch_to_topics": "Auto switch to topic", "provider.api_key": "API Key", + "provider.api_key.tip": "Multiple keys separated by commas", "provider.check": "Check", "provider.get_api_key": "Get API Key", "provider.api_host": "API Host", diff --git a/src/renderer/src/i18n/locales/zh-cn.json b/src/renderer/src/i18n/locales/zh-cn.json index b8b384e6..e7c6ec47 100644 --- a/src/renderer/src/i18n/locales/zh-cn.json +++ b/src/renderer/src/i18n/locales/zh-cn.json @@ -289,6 +289,7 @@ "advanced.title": "高级设置", "advanced.click_assistant_switch_to_topics": "点击助手切换到话题", "provider.api_key": "API 密钥", + "provider.api_key.tip": "多个密钥使用逗号分隔", "provider.check": "检查", "provider.get_api_key": "点击这里获取密钥", "provider.api_host": "API 地址", diff --git a/src/renderer/src/i18n/locales/zh-tw.json b/src/renderer/src/i18n/locales/zh-tw.json index 22d372b6..4a43e4a3 100644 --- a/src/renderer/src/i18n/locales/zh-tw.json +++ b/src/renderer/src/i18n/locales/zh-tw.json @@ -289,6 +289,7 @@ "advanced.title": "進階設定", "advanced.click_assistant_switch_to_topics": "點擊助手切換到話題", "provider.api_key": "API 密鑰", + "provider.api_key.tip": "多個密鑰使用逗號分隔", "provider.check": "檢查", "provider.get_api_key": "獲取 API 密鑰", "provider.api_host": "API 主機地址", diff --git a/src/renderer/src/pages/settings/ProviderSettings/ProviderSetting.tsx b/src/renderer/src/pages/settings/ProviderSettings/ProviderSetting.tsx index d9a06674..18df2c87 100644 --- a/src/renderer/src/pages/settings/ProviderSettings/ProviderSetting.tsx +++ b/src/renderer/src/pages/settings/ProviderSettings/ProviderSetting.tsx @@ -118,7 +118,7 @@ const ProviderSetting: FC = ({ provider: _provider }) => { setApiKey(e.target.value)} + onChange={(e) => setApiKey(e.target.value.replaceAll(',', ','))} onBlur={onUpdateApiKey} spellCheck={false} type="password" @@ -129,10 +129,11 @@ const ProviderSetting: FC = ({ provider: _provider }) => { {apiKeyWebsite && ( - + {t('settings.provider.get_api_key')} + {t('settings.provider.api_key.tip')} )} {t('settings.provider.api_host')} diff --git a/src/renderer/src/providers/AnthropicProvider.ts b/src/renderer/src/providers/AnthropicProvider.ts index 96c11190..60414aac 100644 --- a/src/renderer/src/providers/AnthropicProvider.ts +++ b/src/renderer/src/providers/AnthropicProvider.ts @@ -16,7 +16,7 @@ export default class AnthropicProvider extends BaseProvider { constructor(provider: Provider) { super(provider) - this.sdk = new Anthropic({ apiKey: provider.apiKey, baseURL: this.getBaseURL() }) + this.sdk = new Anthropic({ apiKey: this.apiKey, baseURL: this.getBaseURL() }) } public getBaseURL(): string { diff --git a/src/renderer/src/providers/BaseProvider.ts b/src/renderer/src/providers/BaseProvider.ts index 983bc2be..b490d8ae 100644 --- a/src/renderer/src/providers/BaseProvider.ts +++ b/src/renderer/src/providers/BaseProvider.ts @@ -6,10 +6,12 @@ import OpenAI from 'openai' export default abstract class BaseProvider { protected provider: Provider protected host: string + protected apiKey: string constructor(provider: Provider) { this.provider = provider this.host = this.getBaseURL() + this.apiKey = this.getApiKey() } public getBaseURL(): string { @@ -17,9 +19,31 @@ export default abstract class BaseProvider { return host.endsWith('/') ? host : `${host}/v1/` } + public getApiKey() { + const keys = this.provider.apiKey.split(',').map((key) => key.trim()) + const keyName = `provider:${this.provider.id}:last_used_key` + + if (keys.length === 1) { + return keys[0] + } + + const lastUsedKey = window.keyv.get(keyName) + if (!lastUsedKey) { + window.keyv.set(keyName, keys[0]) + return keys[0] + } + + const currentIndex = keys.indexOf(lastUsedKey) + const nextIndex = (currentIndex + 1) % keys.length + const nextKey = keys[nextIndex] + window.keyv.set(keyName, nextKey) + + return nextKey + } + public defaultHeaders() { return { - 'X-Api-Key': this.provider.apiKey + 'X-Api-Key': this.apiKey } } diff --git a/src/renderer/src/providers/GeminiProvider.ts b/src/renderer/src/providers/GeminiProvider.ts index b07d6b37..8a5f57b3 100644 --- a/src/renderer/src/providers/GeminiProvider.ts +++ b/src/renderer/src/providers/GeminiProvider.ts @@ -23,7 +23,7 @@ export default class GeminiProvider extends BaseProvider { constructor(provider: Provider) { super(provider) - this.sdk = new GoogleGenerativeAI(provider.apiKey) + this.sdk = new GoogleGenerativeAI(this.apiKey) } private async getMessageContents(message: Message): Promise { @@ -231,7 +231,7 @@ export default class GeminiProvider extends BaseProvider { public async models(): Promise { try { const api = this.provider.apiHost + '/v1beta/models' - const { data } = await axios.get(api, { params: { key: this.provider.apiKey } }) + const { data } = await axios.get(api, { params: { key: this.apiKey } }) return data.models.map( (m: any) => ({ diff --git a/src/renderer/src/providers/OpenAIProvider.ts b/src/renderer/src/providers/OpenAIProvider.ts index 8d1cde83..0b615bd0 100644 --- a/src/renderer/src/providers/OpenAIProvider.ts +++ b/src/renderer/src/providers/OpenAIProvider.ts @@ -20,10 +20,11 @@ export default class OpenAIProvider extends BaseProvider { constructor(provider: Provider) { super(provider) + if (provider.id === 'azure-openai') { this.sdk = new AzureOpenAI({ dangerouslyAllowBrowser: true, - apiKey: provider.apiKey, + apiKey: this.apiKey, apiVersion: provider.apiVersion, endpoint: provider.apiHost }) @@ -32,7 +33,7 @@ export default class OpenAIProvider extends BaseProvider { this.sdk = new OpenAI({ dangerouslyAllowBrowser: true, - apiKey: provider.apiKey, + apiKey: this.apiKey, baseURL: this.getBaseURL(), defaultHeaders: this.defaultHeaders() }) diff --git a/src/renderer/src/services/ApiService.ts b/src/renderer/src/services/ApiService.ts index 30e59720..9a76a4e3 100644 --- a/src/renderer/src/services/ApiService.ts +++ b/src/renderer/src/services/ApiService.ts @@ -163,8 +163,6 @@ export async function fetchSuggestions({ messages: Message[] assistant: Assistant }): Promise { - const provider = getAssistantProvider(assistant) - const AI = new AiProvider(provider) const model = assistant.model if (!model) { @@ -179,6 +177,9 @@ export async function fetchSuggestions({ return [] } + const provider = getAssistantProvider(assistant) + const AI = new AiProvider(provider) + try { return await AI.suggestions(filterMessages(messages), assistant) } catch (error: any) {