fix(ProviderSettings): allow embedding model API check and optimize hooks (#12334)

This commit is contained in:
Phantom 2026-01-07 14:13:05 +08:00 committed by GitHub
parent c940b5613f
commit 91b6ed81cc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 22 additions and 13 deletions

View File

@ -5,7 +5,7 @@ import { HStack } from '@renderer/components/Layout'
import { ApiKeyListPopup } from '@renderer/components/Popups/ApiKeyListPopup'
import Selector from '@renderer/components/Selector'
import { HelpTooltip } from '@renderer/components/TooltipIcons'
import { isEmbeddingModel, isRerankModel } from '@renderer/config/models'
import { isRerankModel } from '@renderer/config/models'
import { PROVIDER_URLS } from '@renderer/config/providers'
import { useTheme } from '@renderer/context/ThemeProvider'
import { useAllProviders, useProvider, useProviders } from '@renderer/hooks/useProvider'
@ -129,17 +129,20 @@ const ProviderSetting: FC<Props> = ({ providerId }) => {
checking: false
})
const updateWebSearchProviderKey = ({ apiKey }: { apiKey: string }) => {
provider.id === 'zhipu' && dispatch(updateWebSearchProvider({ id: 'zhipu', apiKey: apiKey.split(',')[0] }))
}
const updateWebSearchProviderKey = useCallback(
({ apiKey }: { apiKey: string }) => {
provider.id === 'zhipu' && dispatch(updateWebSearchProvider({ id: 'zhipu', apiKey: apiKey.split(',')[0] }))
},
[dispatch, provider.id]
)
// eslint-disable-next-line react-hooks/exhaustive-deps
const debouncedUpdateApiKey = useCallback(
debounce((value) => {
updateProvider({ apiKey: formatApiKeys(value) })
updateWebSearchProviderKey({ apiKey: formatApiKeys(value) })
}, 150),
[]
const debouncedUpdateApiKey = useMemo(
() =>
debounce((value: string) => {
updateProvider({ apiKey: formatApiKeys(value) })
updateWebSearchProviderKey({ apiKey: formatApiKeys(value) })
}, 150),
[updateProvider, updateWebSearchProviderKey]
)
// 同步 provider.apiKey 到 localApiKey
@ -225,7 +228,7 @@ const ProviderSetting: FC<Props> = ({ providerId }) => {
return
}
const modelsToCheck = models.filter((model) => !isEmbeddingModel(model) && !isRerankModel(model))
const modelsToCheck = models.filter((model) => !isRerankModel(model))
if (isEmpty(modelsToCheck)) {
window.toast.error({

View File

@ -601,6 +601,13 @@ export function checkApiProvider(provider: Provider): void {
}
}
/**
* Validates that a provider/model pair is working by sending a minimal request.
* @param provider - The provider configuration to test.
* @param model - The model to use for the validation request (chat or embeddings).
* @param timeout - Maximum time (ms) to wait for the request to complete. Defaults to 15000 ms.
* @throws {Error} If the request fails or times out, indicating the API is not usable.
*/
export async function checkApi(provider: Provider, model: Model, timeout = 15000): Promise<void> {
checkApiProvider(provider)
@ -611,7 +618,6 @@ export async function checkApi(provider: Provider, model: Model, timeout = 15000
assistant.prompt = 'test' // 避免部分 provider 空系统提示词会报错
if (isEmbeddingModel(model)) {
// race 超时 15s
logger.silly("it's a embedding model")
const timerPromise = new Promise((_, reject) => setTimeout(() => reject('Timeout'), timeout))
await Promise.race([ai.getEmbeddingDimensions(model), timerPromise])