feat(settings): add website to provider settings

This commit is contained in:
kangfenmao 2024-07-12 13:50:22 +08:00
parent b23f21e669
commit 1729c1e875
7 changed files with 143 additions and 33 deletions

View File

@ -1,5 +1,5 @@
import { FC } from 'react'
import { SettingContainer, SettingDivider, SettingSubtitle, SettingTitle } from './components/SettingComponent'
import { SettingContainer, SettingDivider, SettingSubtitle, SettingTitle } from './components'
import { Input } from 'antd'
import TextArea from 'antd/es/input/TextArea'
import { useDefaultAssistant } from '@renderer/hooks/useAssistant'

View File

@ -1,11 +1,5 @@
import { FC } from 'react'
import {
SettingContainer,
SettingDivider,
SettingRow,
SettingRowTitle,
SettingTitle
} from './components/SettingComponent'
import { SettingContainer, SettingDivider, SettingRow, SettingRowTitle, SettingTitle } from './components'
import { Avatar, message, Upload } from 'antd'
import styled from 'styled-components'
import LocalStorage from '@renderer/services/storage'

View File

@ -1,5 +1,5 @@
import { FC } from 'react'
import { SettingContainer, SettingDivider, SettingTitle } from './components/SettingComponent'
import { SettingContainer, SettingDivider, SettingTitle } from './components'
import { Select } from 'antd'
import { useProviders } from '@renderer/hooks/useProvider'
import { useDefaultModel } from '@renderer/hooks/useAssistant'

View File

@ -102,7 +102,7 @@ const PopupContainer: React.FC<Props> = ({ title, provider, resolve }) => {
)
}
export default class ModalAddPopup {
export default class AddModelPopup {
static topviewId = 0
static hide() {
TopView.hide(this.topviewId)

View File

@ -214,7 +214,7 @@ const Question = styled(QuestionCircleOutlined)`
color: #888;
`
export default class ModelListPopup {
export default class EditModelsPopup {
static topviewId = 0
static hide() {
TopView.hide(this.topviewId)

View File

@ -4,16 +4,91 @@ import styled from 'styled-components'
import { Avatar, Button, Card, Divider, Flex, Input, Switch } from 'antd'
import { useProvider } from '@renderer/hooks/useProvider'
import { groupBy } from 'lodash'
import { SettingContainer, SettingSubtitle, SettingTitle } from './SettingComponent'
import { SettingContainer, SettingSubtitle, SettingTitle } from '.'
import { getModelLogo } from '@renderer/services/provider'
import { EditOutlined, PlusOutlined } from '@ant-design/icons'
import ModalAddPopup from './ModelAddPopup'
import ModelListPopup from './ModelListPopup'
import { EditOutlined, ExportOutlined, PlusOutlined } from '@ant-design/icons'
import AddModelPopup from './AddModelPopup'
import EditModelsPopup from './EditModelsPopup'
import Link from 'antd/es/typography/Link'
interface Props {
provider: Provider
}
const PROVIDER_CONFIG = {
openai: {
websites: {
official: 'https://openai.com/',
apiKey: 'https://platform.openai.com/api-keys',
docs: 'https://platform.openai.com/docs',
models: 'https://platform.openai.com/docs/models'
}
},
silicon: {
websites: {
official: 'https://www.siliconflow.cn/',
apiKey: 'https://cloud.siliconflow.cn/account/ak',
docs: 'https://docs.siliconflow.cn/',
models: 'https://docs.siliconflow.cn/docs/model-names'
}
},
deepseek: {
websites: {
official: 'https://deepseek.com/',
apiKey: 'https://platform.deepseek.com/api_keys',
docs: 'https://platform.deepseek.com/api-docs/',
models: 'https://platform.deepseek.com/api-docs/'
}
},
yi: {
websites: {
official: 'https://platform.lingyiwanwu.com/',
apiKey: 'https://platform.lingyiwanwu.com/apikeys',
docs: 'https://platform.lingyiwanwu.com/docs',
models: 'https://platform.lingyiwanwu.com/docs#%E6%A8%A1%E5%9E%8B'
}
},
zhipu: {
websites: {
official: 'https://open.bigmodel.cn/',
apiKey: 'https://open.bigmodel.cn/usercenter/apikeys',
docs: 'https://open.bigmodel.cn/dev/howuse/introduction',
models: 'https://open.bigmodel.cn/modelcenter/square'
}
},
moonshot: {
websites: {
official: 'https://moonshot.ai/',
apiKey: 'https://platform.moonshot.cn/console/api-keys',
docs: 'https://platform.moonshot.cn/docs/',
models: 'https://platform.moonshot.cn/docs/intro#%E6%A8%A1%E5%9E%8B%E5%88%97%E8%A1%A8'
}
},
openrouter: {
websites: {
official: 'https://openrouter.ai/',
apiKey: 'https://openrouter.ai/settings/keys',
docs: 'https://openrouter.ai/docs/quick-start',
models: 'https://openrouter.ai/docs/models'
}
},
groq: {
websites: {
official: 'https://groq.com/',
apiKey: 'https://console.groq.com/keys',
docs: 'https://console.groq.com/docs/quickstart',
models: 'https://console.groq.com/docs/models'
}
},
ollama: {
websites: {
official: 'https://ollama.com/',
docs: 'https://github.com/ollama/ollama/tree/main/docs',
models: 'https://ollama.com/library'
}
}
}
const ProviderSetting: FC<Props> = ({ provider }) => {
const [apiKey, setApiKey] = useState(provider.apiKey)
const [apiHost, setApiHost] = useState(provider.apiHost)
@ -26,26 +101,28 @@ const ProviderSetting: FC<Props> = ({ provider }) => {
setApiHost(provider.apiHost)
}, [provider])
const onUpdateApiKey = () => {
updateProvider({ ...provider, apiKey })
}
const onUpdateApiKey = () => updateProvider({ ...provider, apiKey })
const onUpdateApiHost = () => updateProvider({ ...provider, apiHost })
const onManageModel = () => EditModelsPopup.show({ provider })
const onAddModel = () => AddModelPopup.show({ title: 'Add Model', provider })
const onUpdateApiHost = () => {
updateProvider({ ...provider, apiHost })
}
const onManageModel = () => {
ModelListPopup.show({ provider })
}
const onAddModel = () => {
ModalAddPopup.show({ title: 'Add Model', provider })
}
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
return (
<SettingContainer>
<SettingTitle>
<span>{provider.name}</span>
<Flex align="center">
<span>{provider.name}</span>
{officialWebsite! && (
<Link target="_blank" href={providerConfig.websites.official}>
<ExportOutlined style={{ marginLeft: '8px', color: 'white', fontSize: '12px' }} />
</Link>
)}
</Flex>
<Switch
defaultValue={provider.enabled}
key={provider.id}
@ -53,7 +130,7 @@ const ProviderSetting: FC<Props> = ({ provider }) => {
/>
</SettingTitle>
<Divider style={{ width: '100%', margin: '10px 0' }} />
<SettingSubtitle>API Key</SettingSubtitle>
<SettingSubtitle style={{ marginTop: 5 }}>API Key</SettingSubtitle>
<Input
value={apiKey}
placeholder="API Key"
@ -61,7 +138,16 @@ const ProviderSetting: FC<Props> = ({ provider }) => {
onBlur={onUpdateApiKey}
spellCheck={false}
disabled={provider.id === 'ollama'}
autoFocus={provider.enabled && apiKey === ''}
/>
{apiKeyWebsite && (
<HelpTextRow>
<HelpText>Get API key from: </HelpText>
<HelpLink target="_blank" href={apiKeyWebsite}>
{provider.name}
</HelpLink>
</HelpTextRow>
)}
<SettingSubtitle>API Host</SettingSubtitle>
<Input
value={apiHost}
@ -83,6 +169,19 @@ const ProviderSetting: FC<Props> = ({ provider }) => {
))}
</Card>
))}
{docsWebsite && (
<HelpTextRow>
<HelpText>Check </HelpText>
<HelpLink target="_blank" href={docsWebsite}>
{provider.name} Docs
</HelpLink>
<HelpText>and</HelpText>
<HelpLink target="_blank" href={modelsWebsite}>
Models
</HelpLink>
<HelpText>for more details</HelpText>
</HelpTextRow>
)}
<Flex gap={10} style={{ marginTop: '10px' }}>
<Button type="primary" onClick={onManageModel} icon={<EditOutlined />}>
Manage
@ -103,4 +202,21 @@ const ModelListItem = styled.div`
padding: 5px 0;
`
const HelpTextRow = styled.div`
display: flex;
flex-direction: row;
align-items: center;
padding: 5px 0;
`
const HelpText = styled.div`
font-size: 11px;
color: #ffffff50;
`
const HelpLink = styled(Link)`
font-size: 11px;
padding: 0 5px;
`
export default ProviderSetting

View File

@ -24,8 +24,8 @@ export const SettingTitle = styled.div`
export const SettingSubtitle = styled.div`
font-size: 12px;
color: var(--color-text-3);
margin: 10px 0;
color: var(--color-text-2);
margin: 15px 0 10px 0;
`
export const SettingDivider = styled(Divider)`