feat(setting): add api check
This commit is contained in:
parent
1729c1e875
commit
d3a163e50a
@ -1,15 +1,16 @@
|
|||||||
import { Provider } from '@renderer/types'
|
import { Provider } from '@renderer/types'
|
||||||
import { FC, useEffect, useState } from 'react'
|
import { FC, useEffect, useState } from 'react'
|
||||||
import styled from 'styled-components'
|
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 { useProvider } from '@renderer/hooks/useProvider'
|
||||||
import { groupBy } from 'lodash'
|
import { groupBy } from 'lodash'
|
||||||
import { SettingContainer, SettingSubtitle, SettingTitle } from '.'
|
import { SettingContainer, SettingSubtitle, SettingTitle } from '.'
|
||||||
import { getModelLogo } from '@renderer/services/provider'
|
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 AddModelPopup from './AddModelPopup'
|
||||||
import EditModelsPopup from './EditModelsPopup'
|
import EditModelsPopup from './EditModelsPopup'
|
||||||
import Link from 'antd/es/typography/Link'
|
import Link from 'antd/es/typography/Link'
|
||||||
|
import { checkApi } from '@renderer/services/api'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
provider: Provider
|
provider: Provider
|
||||||
@ -92,6 +93,8 @@ const PROVIDER_CONFIG = {
|
|||||||
const ProviderSetting: FC<Props> = ({ provider }) => {
|
const ProviderSetting: FC<Props> = ({ provider }) => {
|
||||||
const [apiKey, setApiKey] = useState(provider.apiKey)
|
const [apiKey, setApiKey] = useState(provider.apiKey)
|
||||||
const [apiHost, setApiHost] = useState(provider.apiHost)
|
const [apiHost, setApiHost] = useState(provider.apiHost)
|
||||||
|
const [apiValid, setApiValid] = useState(false)
|
||||||
|
const [apiChecking, setApiChecking] = useState(false)
|
||||||
const { updateProvider, models } = useProvider(provider.id)
|
const { updateProvider, models } = useProvider(provider.id)
|
||||||
|
|
||||||
const modelGroups = groupBy(models, 'group')
|
const modelGroups = groupBy(models, 'group')
|
||||||
@ -106,12 +109,22 @@ const ProviderSetting: FC<Props> = ({ provider }) => {
|
|||||||
const onManageModel = () => EditModelsPopup.show({ provider })
|
const onManageModel = () => EditModelsPopup.show({ provider })
|
||||||
const onAddModel = () => AddModelPopup.show({ title: 'Add Model', 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 providerConfig = PROVIDER_CONFIG[provider.id]
|
||||||
const officialWebsite = providerConfig?.websites?.official
|
const officialWebsite = providerConfig?.websites?.official
|
||||||
const apiKeyWebsite = providerConfig?.websites?.apiKey
|
const apiKeyWebsite = providerConfig?.websites?.apiKey
|
||||||
const docsWebsite = providerConfig?.websites?.docs
|
const docsWebsite = providerConfig?.websites?.docs
|
||||||
const modelsWebsite = providerConfig?.websites?.models
|
const modelsWebsite = providerConfig?.websites?.models
|
||||||
|
|
||||||
|
const apiKeyDisabled = provider.id === 'ollama'
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SettingContainer>
|
<SettingContainer>
|
||||||
<SettingTitle>
|
<SettingTitle>
|
||||||
@ -131,15 +144,22 @@ const ProviderSetting: FC<Props> = ({ provider }) => {
|
|||||||
</SettingTitle>
|
</SettingTitle>
|
||||||
<Divider style={{ width: '100%', margin: '10px 0' }} />
|
<Divider style={{ width: '100%', margin: '10px 0' }} />
|
||||||
<SettingSubtitle style={{ marginTop: 5 }}>API Key</SettingSubtitle>
|
<SettingSubtitle style={{ marginTop: 5 }}>API Key</SettingSubtitle>
|
||||||
<Input
|
<Space.Compact style={{ width: '100%' }}>
|
||||||
value={apiKey}
|
<Input
|
||||||
placeholder="API Key"
|
value={apiKey}
|
||||||
onChange={(e) => setApiKey(e.target.value)}
|
placeholder="API Key"
|
||||||
onBlur={onUpdateApiKey}
|
onChange={(e) => setApiKey(e.target.value)}
|
||||||
spellCheck={false}
|
onBlur={onUpdateApiKey}
|
||||||
disabled={provider.id === 'ollama'}
|
spellCheck={false}
|
||||||
autoFocus={provider.enabled && apiKey === ''}
|
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 && (
|
{apiKeyWebsite && (
|
||||||
<HelpTextRow>
|
<HelpTextRow>
|
||||||
<HelpText>Get API key from: </HelpText>
|
<HelpText>Get API key from: </HelpText>
|
||||||
|
|||||||
@ -20,12 +20,14 @@ export const SettingTitle = styled.div`
|
|||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
font-weight: 900;
|
font-weight: 900;
|
||||||
|
user-select: none;
|
||||||
`
|
`
|
||||||
|
|
||||||
export const SettingSubtitle = styled.div`
|
export const SettingSubtitle = styled.div`
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
color: var(--color-text-2);
|
color: var(--color-text-2);
|
||||||
margin: 15px 0 10px 0;
|
margin: 15px 0 10px 0;
|
||||||
|
user-select: none;
|
||||||
`
|
`
|
||||||
|
|
||||||
export const SettingDivider = styled(Divider)`
|
export const SettingDivider = styled(Divider)`
|
||||||
|
|||||||
@ -104,6 +104,53 @@ export async function fetchMessagesSummary({ messages, assistant }: FetchMessage
|
|||||||
return response.choices[0].message?.content
|
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) {
|
export async function fetchModels(provider: Provider) {
|
||||||
try {
|
try {
|
||||||
const openaiProvider = getOpenAiProvider(provider)
|
const openaiProvider = getOpenAiProvider(provider)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user