fix: 加入账号轮询功能 #293

This commit is contained in:
kangfenmao 2024-11-09 23:11:25 +08:00
parent 61ceca2363
commit 79cabadfb8
9 changed files with 40 additions and 10 deletions

View File

@ -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",

View File

@ -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 地址",

View File

@ -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 主機地址",

View File

@ -118,7 +118,7 @@ const ProviderSetting: FC<Props> = ({ provider: _provider }) => {
<Input.Password
value={apiKey}
placeholder={t('settings.provider.api_key')}
onChange={(e) => setApiKey(e.target.value)}
onChange={(e) => setApiKey(e.target.value.replaceAll('', ','))}
onBlur={onUpdateApiKey}
spellCheck={false}
type="password"
@ -129,10 +129,11 @@ const ProviderSetting: FC<Props> = ({ provider: _provider }) => {
</Button>
</Space.Compact>
{apiKeyWebsite && (
<SettingHelpTextRow>
<SettingHelpTextRow style={{ justifyContent: 'space-between' }}>
<SettingHelpLink target="_blank" href={apiKeyWebsite}>
{t('settings.provider.get_api_key')}
</SettingHelpLink>
<SettingHelpText>{t('settings.provider.api_key.tip')}</SettingHelpText>
</SettingHelpTextRow>
)}
<SettingSubtitle>{t('settings.provider.api_host')}</SettingSubtitle>

View File

@ -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 {

View File

@ -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
}
}

View File

@ -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<Content> {
@ -231,7 +231,7 @@ export default class GeminiProvider extends BaseProvider {
public async models(): Promise<OpenAI.Models.Model[]> {
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) =>
({

View File

@ -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()
})

View File

@ -163,8 +163,6 @@ export async function fetchSuggestions({
messages: Message[]
assistant: Assistant
}): Promise<Suggestion[]> {
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) {