feat(settings): default modal settings

This commit is contained in:
kangfenmao 2024-07-05 13:17:54 +08:00
parent 8398d93b03
commit 7dc0b98f3a
14 changed files with 189 additions and 140 deletions

View File

@ -28,7 +28,7 @@ const Sidebar: FC = () => {
</Menus>
</MainMenus>
<Menus>
<StyledLink to="/settings/common">
<StyledLink to="/settings/general">
<Icon className={pathname.startsWith('/settings') ? 'active' : ''}>
<i className="iconfont icon-setting"></i>
</Icon>

View File

@ -38,46 +38,6 @@ export const SYSTEM_MODELS: Record<string, SystemModel[]> = {
}
],
silicon: [
{
id: 'deepseek-ai/DeepSeek-V2-Chat',
provider: 'silicon',
name: 'DeepSeek-V2-Chat',
group: 'DeepSeek',
temperature: 0.7,
defaultEnabled: true
},
{
id: 'deepseek-ai/DeepSeek-Coder-V2-Instruct',
provider: 'silicon',
name: 'DeepSeek-Coder-V2-Instruct',
group: 'DeepSeek',
temperature: 0.7,
defaultEnabled: true
},
{
id: 'deepseek-ai/deepseek-llm-67b-chat',
provider: 'silicon',
name: 'deepseek-llm-67b-chat',
group: 'DeepSeek',
temperature: 0.7,
defaultEnabled: false
},
{
id: 'google/gemma-2-27b-it',
provider: 'silicon',
name: 'gemma-2-27b-it',
group: 'Gemma',
temperature: 0.7,
defaultEnabled: false
},
{
id: 'google/gemma-2-9b-it',
provider: 'silicon',
name: 'gemma-2-9b-it',
group: 'Gemma',
temperature: 0.7,
defaultEnabled: false
},
{
id: 'Qwen/Qwen2-7B-Instruct',
provider: 'silicon',
@ -142,6 +102,46 @@ export const SYSTEM_MODELS: Record<string, SystemModel[]> = {
temperature: 0.7,
defaultEnabled: false
},
{
id: 'deepseek-ai/DeepSeek-V2-Chat',
provider: 'silicon',
name: 'DeepSeek-V2-Chat',
group: 'DeepSeek',
temperature: 0.7,
defaultEnabled: false
},
{
id: 'deepseek-ai/DeepSeek-Coder-V2-Instruct',
provider: 'silicon',
name: 'DeepSeek-Coder-V2-Instruct',
group: 'DeepSeek',
temperature: 0.7,
defaultEnabled: false
},
{
id: 'deepseek-ai/deepseek-llm-67b-chat',
provider: 'silicon',
name: 'deepseek-llm-67b-chat',
group: 'DeepSeek',
temperature: 0.7,
defaultEnabled: false
},
{
id: 'google/gemma-2-27b-it',
provider: 'silicon',
name: 'gemma-2-27b-it',
group: 'Gemma',
temperature: 0.7,
defaultEnabled: false
},
{
id: 'google/gemma-2-9b-it',
provider: 'silicon',
name: 'gemma-2-9b-it',
group: 'Gemma',
temperature: 0.7,
defaultEnabled: false
},
{
id: 'THUDM/glm-4-9b-chat',
provider: 'silicon',

View File

@ -9,6 +9,7 @@ import {
removeAssistant,
updateAssistant
} from '@renderer/store/assistants'
import { setDefaultModel as _setDefaultModel, setTopicNamingModel as _setTopicNamingModel } from '@renderer/store/llm'
import { Assistant, Model, Topic } from '@renderer/types'
import localforage from 'localforage'
@ -19,14 +20,14 @@ export function useAssistants() {
return {
assistants,
addAssistant: (assistant: Assistant) => dispatch(addAssistant(assistant)),
updateAssistant: (assistant: Assistant) => dispatch(updateAssistant(assistant)),
removeAssistant: (id: string) => {
dispatch(removeAssistant({ id }))
const assistant = assistants.find((a) => a.id === id)
if (assistant) {
assistant.topics.forEach((id) => localforage.removeItem(`topic:${id}`))
}
},
updateAssistant: (assistant: Assistant) => dispatch(updateAssistant(assistant))
}
}
}
@ -38,25 +39,22 @@ export function useAssistant(id: string) {
return {
assistant,
model: assistant?.model ?? defaultModel,
addTopic: (topic: Topic) => {
dispatch(_addTopic({ assistantId: assistant.id, topic }))
},
removeTopic: (topic: Topic) => {
dispatch(_removeTopic({ assistantId: assistant.id, topic }))
},
updateTopic: (topic: Topic) => {
dispatch(_updateTopic({ assistantId: assistant.id, topic }))
},
removeAllTopics: () => {
dispatch(_removeAllTopics({ assistantId: assistant.id }))
},
setModel: (model: Model) => {
dispatch(_setModel({ assistantId: assistant.id, model }))
}
addTopic: (topic: Topic) => dispatch(_addTopic({ assistantId: assistant.id, topic })),
removeTopic: (topic: Topic) => dispatch(_removeTopic({ assistantId: assistant.id, topic })),
updateTopic: (topic: Topic) => dispatch(_updateTopic({ assistantId: assistant.id, topic })),
removeAllTopics: () => dispatch(_removeAllTopics({ assistantId: assistant.id })),
setModel: (model: Model) => dispatch(_setModel({ assistantId: assistant.id, model }))
}
}
export function useDefaultModel() {
const defaultModel = useAppSelector((state) => state.llm.defaultModel)
return { defaultModel }
const { defaultModel, topicNamingModel } = useAppSelector((state) => state.llm)
const dispatch = useAppDispatch()
return {
defaultModel,
topicNamingModel,
setDefaultModel: (model: Model) => dispatch(_setDefaultModel({ model })),
setTopicNamingModel: (model: Model) => dispatch(_setTopicNamingModel({ model }))
}
}

View File

@ -32,5 +32,5 @@ export function useProviderByAssistant(assistant: Assistant) {
}
export function useSystemProviders() {
return useAppSelector((state) => state.llm.providers.filter((p) => p.isSystem)) as unknown as Provider
return useAppSelector((state) => state.llm.providers.filter((p) => p.isSystem))
}

View File

@ -1,11 +1,11 @@
import { FC } from 'react'
import styled from 'styled-components'
const DefaultAssistantSetting: FC = () => {
const AssistantSettings: FC = () => {
return <Container>Default Assistant</Container>
}
const Container = styled.div`
padding: 20px;
`
export default DefaultAssistantSetting
export default AssistantSettings

View File

@ -1,11 +0,0 @@
import { FC } from 'react'
import styled from 'styled-components'
const DeveloperSetting: FC = () => {
return <Container>Developer</Container>
}
const Container = styled.div`
padding: 20px;
`
export default DeveloperSetting

View File

@ -1,11 +1,11 @@
import { FC } from 'react'
import styled from 'styled-components'
const CommonSettings: FC = () => {
return <Container>Common Settings</Container>
const GeneralSettings: FC = () => {
return <Container>General Settings</Container>
}
const Container = styled.div`
padding: 20px;
`
export default CommonSettings
export default GeneralSettings

View File

@ -0,0 +1,51 @@
import { FC } from 'react'
import { SettingContainer, SettingDivider, SettingTitle } from './components/SettingComponent'
import { Select } from 'antd'
import { useProviders } from '@renderer/hooks/useProvider'
import { useDefaultModel } from '@renderer/hooks/useAssistant'
import { find } from 'lodash'
import { Model } from '@renderer/types'
const ModelSettings: FC = () => {
const { defaultModel, setDefaultModel, setTopicNamingModel } = useDefaultModel()
const providers = useProviders()
const allModels = providers.map((p) => p.models).flat()
return (
<SettingContainer>
<SettingTitle>Default Assistant Model</SettingTitle>
<SettingDivider />
<Select
defaultValue={defaultModel.id}
style={{ width: 200 }}
onChange={(id) => setDefaultModel(find(allModels, { id }) as Model)}
options={providers.map((p) => ({
label: p.name,
title: p.name,
options: p.models.map((m) => ({
label: m.name,
value: m.id
}))
}))}
/>
<div style={{ height: 40 }} />
<SettingTitle>Topic Naming Model</SettingTitle>
<SettingDivider />
<Select
defaultValue={defaultModel.id}
style={{ width: 200 }}
onChange={(id) => setTopicNamingModel(find(allModels, { id }) as Model)}
options={providers.map((p) => ({
label: p.name,
title: p.name,
options: p.models.map((m) => ({
label: m.name,
value: m.id
}))
}))}
/>
</SettingContainer>
)
}
export default ModelSettings

View File

@ -4,8 +4,7 @@ import { FC, useState } from 'react'
import styled from 'styled-components'
import ModalProviderSetting from './components/ModalProviderSetting'
// OpenAI Silicon deepseek Groq
const LanguageModelsSettings: FC = () => {
const ProviderSettings: FC = () => {
const providers = useSystemProviders()
const [selectedProvider, setSelectedProvider] = useState<Provider>(providers[0])
@ -61,4 +60,4 @@ const ProviderListItem = styled.div`
}
`
export default LanguageModelsSettings
export default ProviderSettings

View File

@ -2,11 +2,11 @@ import { Navbar, NavbarCenter } from '@renderer/components/app/Navbar'
import { FC } from 'react'
import { Link, Route, Routes, useLocation } from 'react-router-dom'
import styled from 'styled-components'
import CommonSettings from './CommonSettings'
import GeneralSettings from './GeneralSettings'
import AboutSettings from './AboutSettings'
import DefaultAssistantSetting from './DefaultAssistantSetting'
import SystemAssistantSettings from './SystemAssistantSettings'
import LanguageModelsSettings from './LanguageModelsSettings'
import AssistantSettings from './AssistantSettings'
import ModelSettings from './ModelSettings'
import ProviderSettings from './ProviderSettings'
const SettingsPage: FC = () => {
const { pathname } = useLocation()
@ -20,17 +20,17 @@ const SettingsPage: FC = () => {
</Navbar>
<ContentContainer>
<SettingMenus>
<MenuItemLink to="/settings/common">
<MenuItem className={isRoute('/settings/common')}>Common Settings</MenuItem>
<MenuItemLink to="/settings/general">
<MenuItem className={isRoute('/settings/general')}>General</MenuItem>
</MenuItemLink>
<MenuItemLink to="/settings/llm">
<MenuItem className={isRoute('/settings/llm')}>Language Model</MenuItem>
<MenuItemLink to="/settings/provider">
<MenuItem className={isRoute('/settings/provider')}>Model Provider</MenuItem>
</MenuItemLink>
<MenuItemLink to="/settings/system-assistant">
<MenuItem className={isRoute('/settings/system-assistant')}>System Assistant</MenuItem>
<MenuItemLink to="/settings/model">
<MenuItem className={isRoute('/settings/model')}>Model Settings</MenuItem>
</MenuItemLink>
<MenuItemLink to="/settings/default-assistant">
<MenuItem className={isRoute('/settings/default-assistant')}>Default Assistant</MenuItem>
<MenuItemLink to="/settings/assistant">
<MenuItem className={isRoute('/settings/assistant')}>Default Assistant</MenuItem>
</MenuItemLink>
<MenuItemLink to="/settings/about">
<MenuItem className={isRoute('/settings/about')}>About</MenuItem>
@ -38,10 +38,10 @@ const SettingsPage: FC = () => {
</SettingMenus>
<SettingContent>
<Routes>
<Route path="common" element={<CommonSettings />} />
<Route path="system-assistant" element={<SystemAssistantSettings />} />
<Route path="default-assistant" element={<DefaultAssistantSetting />} />
<Route path="llm" element={<LanguageModelsSettings />} />
<Route path="general" element={<GeneralSettings />} />
<Route path="provider" element={<ProviderSettings />} />
<Route path="model" element={<ModelSettings />} />
<Route path="assistant" element={<AssistantSettings />} />
<Route path="about" element={<AboutSettings />} />
</Routes>
</SettingContent>

View File

@ -1,11 +0,0 @@
import { FC } from 'react'
import styled from 'styled-components'
const SystemAssistantSettings: FC = () => {
return <Container>System Assistant</Container>
}
const Container = styled.div`
padding: 20px;
`
export default SystemAssistantSettings

View File

@ -5,6 +5,7 @@ import { Button, Card, Divider, Input } from 'antd'
import { useProvider } from '@renderer/hooks/useProvider'
import ModalListPopup from '@renderer/components/Popups/ModalListPopup'
import { groupBy } from 'lodash'
import { SettingContainer, SettingSubtitle, SettingTitle } from './SettingComponent'
interface Props {
provider: Provider
@ -35,10 +36,10 @@ const ModalProviderSetting: FC<Props> = ({ provider }) => {
}
return (
<Container>
<Title>{provider.name}</Title>
<SettingContainer>
<SettingTitle>{provider.name}</SettingTitle>
<Divider style={{ width: '100%', margin: '10px 0' }} />
<SubTitle>API Key</SubTitle>
<SettingSubtitle>API Key</SettingSubtitle>
<Input
value={apiKey}
placeholder="API Key"
@ -46,14 +47,14 @@ const ModalProviderSetting: FC<Props> = ({ provider }) => {
onBlur={onUpdateApiKey}
spellCheck={false}
/>
<SubTitle>API Host</SubTitle>
<SettingSubtitle>API Host</SettingSubtitle>
<Input
value={apiHost}
placeholder="API Host"
onChange={(e) => setApiHost(e.target.value)}
onBlur={onUpdateApiHost}
/>
<SubTitle>Models</SubTitle>
<SettingSubtitle>Models</SettingSubtitle>
{Object.keys(modelGroups).map((group) => (
<Card key={group} type="inner" title={group} style={{ marginBottom: '10px' }} size="small">
{modelGroups[group].map((model) => (
@ -64,36 +65,10 @@ const ModalProviderSetting: FC<Props> = ({ provider }) => {
<Button type="primary" style={{ width: '100px', marginTop: '10px' }} onClick={onAddModal}>
Edit Models
</Button>
</Container>
</SettingContainer>
)
}
const Container = styled.div`
display: flex;
flex-direction: column;
flex: 1;
height: calc(100vh - var(--navbar-height));
padding: 15px;
overflow-y: scroll;
&::-webkit-scrollbar {
display: none;
}
`
const Title = styled.div`
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
`
const SubTitle = styled.div`
font-size: 12px;
color: var(--color-text-3);
margin: 10px 0;
`
const ModelListItem = styled.div`
display: flex;
flex-direction: row;

View File

@ -0,0 +1,32 @@
import { Divider } from 'antd'
import styled from 'styled-components'
export const SettingContainer = styled.div`
display: flex;
flex-direction: column;
flex: 1;
height: calc(100vh - var(--navbar-height));
padding: 15px;
overflow-y: scroll;
&::-webkit-scrollbar {
display: none;
}
`
export const SettingTitle = styled.div`
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
`
export const SettingSubtitle = styled.div`
font-size: 12px;
color: var(--color-text-3);
margin: 10px 0;
`
export const SettingDivider = styled(Divider)`
margin: 10px 0;
`

View File

@ -6,10 +6,12 @@ import { uniqBy } from 'lodash'
export interface LlmState {
providers: Provider[]
defaultModel: Model
topicNamingModel: Model
}
const initialState: LlmState = {
defaultModel: SYSTEM_MODELS.openai[0],
topicNamingModel: SYSTEM_MODELS.openai[0],
providers: [
{
id: 'openai',
@ -78,10 +80,24 @@ const settingsSlice = createSlice({
}
: p
)
},
setDefaultModel: (state, action: PayloadAction<{ model: Model }>) => {
state.defaultModel = action.payload.model
},
setTopicNamingModel: (state, action: PayloadAction<{ model: Model }>) => {
state.topicNamingModel = action.payload.model
}
}
})
export const { updateProvider, addProvider, removeProvider, addModel, removeModel } = settingsSlice.actions
export const {
updateProvider,
addProvider,
removeProvider,
addModel,
removeModel,
setDefaultModel,
setTopicNamingModel
} = settingsSlice.actions
export default settingsSlice.reducer