feat(settings): add website to provider settings
This commit is contained in:
parent
b23f21e669
commit
1729c1e875
@ -1,5 +1,5 @@
|
|||||||
import { FC } from 'react'
|
import { FC } from 'react'
|
||||||
import { SettingContainer, SettingDivider, SettingSubtitle, SettingTitle } from './components/SettingComponent'
|
import { SettingContainer, SettingDivider, SettingSubtitle, SettingTitle } from './components'
|
||||||
import { Input } from 'antd'
|
import { Input } from 'antd'
|
||||||
import TextArea from 'antd/es/input/TextArea'
|
import TextArea from 'antd/es/input/TextArea'
|
||||||
import { useDefaultAssistant } from '@renderer/hooks/useAssistant'
|
import { useDefaultAssistant } from '@renderer/hooks/useAssistant'
|
||||||
|
|||||||
@ -1,11 +1,5 @@
|
|||||||
import { FC } from 'react'
|
import { FC } from 'react'
|
||||||
import {
|
import { SettingContainer, SettingDivider, SettingRow, SettingRowTitle, SettingTitle } from './components'
|
||||||
SettingContainer,
|
|
||||||
SettingDivider,
|
|
||||||
SettingRow,
|
|
||||||
SettingRowTitle,
|
|
||||||
SettingTitle
|
|
||||||
} from './components/SettingComponent'
|
|
||||||
import { Avatar, message, Upload } from 'antd'
|
import { Avatar, message, Upload } from 'antd'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components'
|
||||||
import LocalStorage from '@renderer/services/storage'
|
import LocalStorage from '@renderer/services/storage'
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { FC } from 'react'
|
import { FC } from 'react'
|
||||||
import { SettingContainer, SettingDivider, SettingTitle } from './components/SettingComponent'
|
import { SettingContainer, SettingDivider, SettingTitle } from './components'
|
||||||
import { Select } from 'antd'
|
import { Select } from 'antd'
|
||||||
import { useProviders } from '@renderer/hooks/useProvider'
|
import { useProviders } from '@renderer/hooks/useProvider'
|
||||||
import { useDefaultModel } from '@renderer/hooks/useAssistant'
|
import { useDefaultModel } from '@renderer/hooks/useAssistant'
|
||||||
|
|||||||
@ -102,7 +102,7 @@ const PopupContainer: React.FC<Props> = ({ title, provider, resolve }) => {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class ModalAddPopup {
|
export default class AddModelPopup {
|
||||||
static topviewId = 0
|
static topviewId = 0
|
||||||
static hide() {
|
static hide() {
|
||||||
TopView.hide(this.topviewId)
|
TopView.hide(this.topviewId)
|
||||||
@ -214,7 +214,7 @@ const Question = styled(QuestionCircleOutlined)`
|
|||||||
color: #888;
|
color: #888;
|
||||||
`
|
`
|
||||||
|
|
||||||
export default class ModelListPopup {
|
export default class EditModelsPopup {
|
||||||
static topviewId = 0
|
static topviewId = 0
|
||||||
static hide() {
|
static hide() {
|
||||||
TopView.hide(this.topviewId)
|
TopView.hide(this.topviewId)
|
||||||
@ -4,16 +4,91 @@ import styled from 'styled-components'
|
|||||||
import { Avatar, Button, Card, Divider, Flex, Input, Switch } from 'antd'
|
import { Avatar, Button, Card, Divider, Flex, Input, 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 './SettingComponent'
|
import { SettingContainer, SettingSubtitle, SettingTitle } from '.'
|
||||||
import { getModelLogo } from '@renderer/services/provider'
|
import { getModelLogo } from '@renderer/services/provider'
|
||||||
import { EditOutlined, PlusOutlined } from '@ant-design/icons'
|
import { EditOutlined, ExportOutlined, PlusOutlined } from '@ant-design/icons'
|
||||||
import ModalAddPopup from './ModelAddPopup'
|
import AddModelPopup from './AddModelPopup'
|
||||||
import ModelListPopup from './ModelListPopup'
|
import EditModelsPopup from './EditModelsPopup'
|
||||||
|
import Link from 'antd/es/typography/Link'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
provider: Provider
|
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 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)
|
||||||
@ -26,26 +101,28 @@ const ProviderSetting: FC<Props> = ({ provider }) => {
|
|||||||
setApiHost(provider.apiHost)
|
setApiHost(provider.apiHost)
|
||||||
}, [provider])
|
}, [provider])
|
||||||
|
|
||||||
const onUpdateApiKey = () => {
|
const onUpdateApiKey = () => updateProvider({ ...provider, apiKey })
|
||||||
updateProvider({ ...provider, apiKey })
|
const onUpdateApiHost = () => updateProvider({ ...provider, apiHost })
|
||||||
}
|
const onManageModel = () => EditModelsPopup.show({ provider })
|
||||||
|
const onAddModel = () => AddModelPopup.show({ title: 'Add Model', provider })
|
||||||
|
|
||||||
const onUpdateApiHost = () => {
|
const providerConfig = PROVIDER_CONFIG[provider.id]
|
||||||
updateProvider({ ...provider, apiHost })
|
const officialWebsite = providerConfig?.websites?.official
|
||||||
}
|
const apiKeyWebsite = providerConfig?.websites?.apiKey
|
||||||
|
const docsWebsite = providerConfig?.websites?.docs
|
||||||
const onManageModel = () => {
|
const modelsWebsite = providerConfig?.websites?.models
|
||||||
ModelListPopup.show({ provider })
|
|
||||||
}
|
|
||||||
|
|
||||||
const onAddModel = () => {
|
|
||||||
ModalAddPopup.show({ title: 'Add Model', provider })
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SettingContainer>
|
<SettingContainer>
|
||||||
<SettingTitle>
|
<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
|
<Switch
|
||||||
defaultValue={provider.enabled}
|
defaultValue={provider.enabled}
|
||||||
key={provider.id}
|
key={provider.id}
|
||||||
@ -53,7 +130,7 @@ const ProviderSetting: FC<Props> = ({ provider }) => {
|
|||||||
/>
|
/>
|
||||||
</SettingTitle>
|
</SettingTitle>
|
||||||
<Divider style={{ width: '100%', margin: '10px 0' }} />
|
<Divider style={{ width: '100%', margin: '10px 0' }} />
|
||||||
<SettingSubtitle>API Key</SettingSubtitle>
|
<SettingSubtitle style={{ marginTop: 5 }}>API Key</SettingSubtitle>
|
||||||
<Input
|
<Input
|
||||||
value={apiKey}
|
value={apiKey}
|
||||||
placeholder="API Key"
|
placeholder="API Key"
|
||||||
@ -61,7 +138,16 @@ const ProviderSetting: FC<Props> = ({ provider }) => {
|
|||||||
onBlur={onUpdateApiKey}
|
onBlur={onUpdateApiKey}
|
||||||
spellCheck={false}
|
spellCheck={false}
|
||||||
disabled={provider.id === 'ollama'}
|
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>
|
<SettingSubtitle>API Host</SettingSubtitle>
|
||||||
<Input
|
<Input
|
||||||
value={apiHost}
|
value={apiHost}
|
||||||
@ -83,6 +169,19 @@ const ProviderSetting: FC<Props> = ({ provider }) => {
|
|||||||
))}
|
))}
|
||||||
</Card>
|
</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' }}>
|
<Flex gap={10} style={{ marginTop: '10px' }}>
|
||||||
<Button type="primary" onClick={onManageModel} icon={<EditOutlined />}>
|
<Button type="primary" onClick={onManageModel} icon={<EditOutlined />}>
|
||||||
Manage
|
Manage
|
||||||
@ -103,4 +202,21 @@ const ModelListItem = styled.div`
|
|||||||
padding: 5px 0;
|
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
|
export default ProviderSetting
|
||||||
|
|||||||
@ -24,8 +24,8 @@ export const SettingTitle = styled.div`
|
|||||||
|
|
||||||
export const SettingSubtitle = styled.div`
|
export const SettingSubtitle = styled.div`
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
color: var(--color-text-3);
|
color: var(--color-text-2);
|
||||||
margin: 10px 0;
|
margin: 15px 0 10px 0;
|
||||||
`
|
`
|
||||||
|
|
||||||
export const SettingDivider = styled(Divider)`
|
export const SettingDivider = styled(Divider)`
|
||||||
Loading…
x
Reference in New Issue
Block a user