feat(setting): add api check
This commit is contained in:
parent
1729c1e875
commit
d3a163e50a
@ -1,15 +1,16 @@
|
||||
import { Provider } from '@renderer/types'
|
||||
import { FC, useEffect, useState } from 'react'
|
||||
import styled from 'styled-components'
|
||||
import { Avatar, Button, Card, Divider, Flex, Input, Switch } from 'antd'
|
||||
import { Avatar, Button, Card, Divider, Flex, Input, Space, Switch } from 'antd'
|
||||
import { useProvider } from '@renderer/hooks/useProvider'
|
||||
import { groupBy } from 'lodash'
|
||||
import { SettingContainer, SettingSubtitle, SettingTitle } from '.'
|
||||
import { getModelLogo } from '@renderer/services/provider'
|
||||
import { EditOutlined, ExportOutlined, PlusOutlined } from '@ant-design/icons'
|
||||
import { CheckOutlined, EditOutlined, ExportOutlined, LoadingOutlined, PlusOutlined } from '@ant-design/icons'
|
||||
import AddModelPopup from './AddModelPopup'
|
||||
import EditModelsPopup from './EditModelsPopup'
|
||||
import Link from 'antd/es/typography/Link'
|
||||
import { checkApi } from '@renderer/services/api'
|
||||
|
||||
interface Props {
|
||||
provider: Provider
|
||||
@ -92,6 +93,8 @@ const PROVIDER_CONFIG = {
|
||||
const ProviderSetting: FC<Props> = ({ provider }) => {
|
||||
const [apiKey, setApiKey] = useState(provider.apiKey)
|
||||
const [apiHost, setApiHost] = useState(provider.apiHost)
|
||||
const [apiValid, setApiValid] = useState(false)
|
||||
const [apiChecking, setApiChecking] = useState(false)
|
||||
const { updateProvider, models } = useProvider(provider.id)
|
||||
|
||||
const modelGroups = groupBy(models, 'group')
|
||||
@ -106,12 +109,22 @@ const ProviderSetting: FC<Props> = ({ provider }) => {
|
||||
const onManageModel = () => EditModelsPopup.show({ provider })
|
||||
const onAddModel = () => AddModelPopup.show({ title: 'Add Model', provider })
|
||||
|
||||
const onCheckApi = async () => {
|
||||
setApiChecking(true)
|
||||
const valid = await checkApi({ ...provider, apiKey, apiHost })
|
||||
setApiValid(valid)
|
||||
setApiChecking(false)
|
||||
setTimeout(() => setApiValid(false), 3000)
|
||||
}
|
||||
|
||||
const providerConfig = PROVIDER_CONFIG[provider.id]
|
||||
const officialWebsite = providerConfig?.websites?.official
|
||||
const apiKeyWebsite = providerConfig?.websites?.apiKey
|
||||
const docsWebsite = providerConfig?.websites?.docs
|
||||
const modelsWebsite = providerConfig?.websites?.models
|
||||
|
||||
const apiKeyDisabled = provider.id === 'ollama'
|
||||
|
||||
return (
|
||||
<SettingContainer>
|
||||
<SettingTitle>
|
||||
@ -131,15 +144,22 @@ const ProviderSetting: FC<Props> = ({ provider }) => {
|
||||
</SettingTitle>
|
||||
<Divider style={{ width: '100%', margin: '10px 0' }} />
|
||||
<SettingSubtitle style={{ marginTop: 5 }}>API Key</SettingSubtitle>
|
||||
<Space.Compact style={{ width: '100%' }}>
|
||||
<Input
|
||||
value={apiKey}
|
||||
placeholder="API Key"
|
||||
onChange={(e) => setApiKey(e.target.value)}
|
||||
onBlur={onUpdateApiKey}
|
||||
spellCheck={false}
|
||||
disabled={provider.id === 'ollama'}
|
||||
disabled={apiKeyDisabled}
|
||||
autoFocus={provider.enabled && apiKey === ''}
|
||||
/>
|
||||
{!apiKeyDisabled && (
|
||||
<Button type={apiValid ? 'primary' : 'default'} ghost={apiValid} onClick={onCheckApi}>
|
||||
{apiChecking ? <LoadingOutlined spin /> : apiValid ? <CheckOutlined /> : 'Check'}
|
||||
</Button>
|
||||
)}
|
||||
</Space.Compact>
|
||||
{apiKeyWebsite && (
|
||||
<HelpTextRow>
|
||||
<HelpText>Get API key from: </HelpText>
|
||||
|
||||
@ -20,12 +20,14 @@ export const SettingTitle = styled.div`
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
font-weight: 900;
|
||||
user-select: none;
|
||||
`
|
||||
|
||||
export const SettingSubtitle = styled.div`
|
||||
font-size: 12px;
|
||||
color: var(--color-text-2);
|
||||
margin: 15px 0 10px 0;
|
||||
user-select: none;
|
||||
`
|
||||
|
||||
export const SettingDivider = styled(Divider)`
|
||||
|
||||
@ -104,6 +104,53 @@ export async function fetchMessagesSummary({ messages, assistant }: FetchMessage
|
||||
return response.choices[0].message?.content
|
||||
}
|
||||
|
||||
export async function checkApi(provider: Provider) {
|
||||
const openaiProvider = getOpenAiProvider(provider)
|
||||
const model = provider.models[0]
|
||||
const key = 'api-check'
|
||||
const style = { marginTop: '3vh' }
|
||||
|
||||
if (!provider.apiKey) {
|
||||
window.message.error({ content: 'Please enter your API key first', key, style })
|
||||
return false
|
||||
}
|
||||
|
||||
if (!provider.apiHost) {
|
||||
window.message.error({ content: 'Please enter your API host first', key, style })
|
||||
return false
|
||||
}
|
||||
|
||||
if (!model) {
|
||||
window.message.error({ content: 'Please select a model first', key, style })
|
||||
return false
|
||||
}
|
||||
|
||||
let valid = false
|
||||
let errorMessage = ''
|
||||
|
||||
try {
|
||||
const response = await openaiProvider.chat.completions.create({
|
||||
model: model.id,
|
||||
messages: [{ role: 'user', content: 'hello' }],
|
||||
stream: false
|
||||
})
|
||||
|
||||
valid = Boolean(response?.choices[0].message)
|
||||
} catch (error) {
|
||||
errorMessage = (error as Error).message
|
||||
valid = false
|
||||
}
|
||||
|
||||
window.message[valid ? 'success' : 'error']({
|
||||
key: 'api-check',
|
||||
style: { marginTop: '3vh' },
|
||||
duration: valid ? 2 : 8,
|
||||
content: valid ? 'API connection successful' : 'API connection failed ' + errorMessage
|
||||
})
|
||||
|
||||
return valid
|
||||
}
|
||||
|
||||
export async function fetchModels(provider: Provider) {
|
||||
try {
|
||||
const openaiProvider = getOpenAiProvider(provider)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user