diff --git a/src/renderer/src/assets/images/models/chatglm.jpeg b/src/renderer/src/assets/images/models/chatglm.jpeg new file mode 100644 index 00000000..ec40bf96 Binary files /dev/null and b/src/renderer/src/assets/images/models/chatglm.jpeg differ diff --git a/src/renderer/src/assets/images/models/chatgpt.svg b/src/renderer/src/assets/images/models/chatgpt.svg new file mode 100644 index 00000000..4005d2dd --- /dev/null +++ b/src/renderer/src/assets/images/models/chatgpt.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/src/renderer/src/assets/images/models/deepseek.png b/src/renderer/src/assets/images/models/deepseek.png new file mode 100644 index 00000000..f9af429e Binary files /dev/null and b/src/renderer/src/assets/images/models/deepseek.png differ diff --git a/src/renderer/src/assets/images/models/gemma.jpeg b/src/renderer/src/assets/images/models/gemma.jpeg new file mode 100644 index 00000000..3ccbd8ee Binary files /dev/null and b/src/renderer/src/assets/images/models/gemma.jpeg differ diff --git a/src/renderer/src/assets/images/models/llama.jpeg b/src/renderer/src/assets/images/models/llama.jpeg new file mode 100644 index 00000000..f15e5931 Binary files /dev/null and b/src/renderer/src/assets/images/models/llama.jpeg differ diff --git a/src/renderer/src/assets/images/models/mixtral.jpeg b/src/renderer/src/assets/images/models/mixtral.jpeg new file mode 100644 index 00000000..005e8ca2 Binary files /dev/null and b/src/renderer/src/assets/images/models/mixtral.jpeg differ diff --git a/src/renderer/src/assets/images/models/qwen.jpeg b/src/renderer/src/assets/images/models/qwen.jpeg new file mode 100644 index 00000000..860b309a Binary files /dev/null and b/src/renderer/src/assets/images/models/qwen.jpeg differ diff --git a/src/renderer/src/assets/images/models/yi.svg b/src/renderer/src/assets/images/models/yi.svg new file mode 100644 index 00000000..83ebd22d --- /dev/null +++ b/src/renderer/src/assets/images/models/yi.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/src/renderer/src/assets/images/providers/deepseek.png b/src/renderer/src/assets/images/providers/deepseek.png new file mode 100644 index 00000000..f9af429e Binary files /dev/null and b/src/renderer/src/assets/images/providers/deepseek.png differ diff --git a/src/renderer/src/assets/images/providers/groq.png b/src/renderer/src/assets/images/providers/groq.png new file mode 100644 index 00000000..31564145 Binary files /dev/null and b/src/renderer/src/assets/images/providers/groq.png differ diff --git a/src/renderer/src/assets/images/providers/openai.jpeg b/src/renderer/src/assets/images/providers/openai.jpeg new file mode 100644 index 00000000..293a43d3 Binary files /dev/null and b/src/renderer/src/assets/images/providers/openai.jpeg differ diff --git a/src/renderer/src/assets/images/providers/silicon.png b/src/renderer/src/assets/images/providers/silicon.png new file mode 100644 index 00000000..d54921c6 Binary files /dev/null and b/src/renderer/src/assets/images/providers/silicon.png differ diff --git a/src/renderer/src/assets/images/providers/yi.svg b/src/renderer/src/assets/images/providers/yi.svg new file mode 100644 index 00000000..19806791 --- /dev/null +++ b/src/renderer/src/assets/images/providers/yi.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/src/renderer/src/assets/styles/index.scss b/src/renderer/src/assets/styles/index.scss index 18726823..32191b63 100644 --- a/src/renderer/src/assets/styles/index.scss +++ b/src/renderer/src/assets/styles/index.scss @@ -94,3 +94,7 @@ body, flex-direction: row; flex: 1; } + +#inputbar .ant-input { + resize: none; +} diff --git a/src/renderer/src/pages/home/components/Inputbar.tsx b/src/renderer/src/pages/home/components/Inputbar.tsx index 94336e52..8514ca67 100644 --- a/src/renderer/src/pages/home/components/Inputbar.tsx +++ b/src/renderer/src/pages/home/components/Inputbar.tsx @@ -100,7 +100,7 @@ const Inputbar: FC = ({ assistant, setActiveTopic }) => { }, [assistant]) return ( - + @@ -144,7 +144,7 @@ const Inputbar: FC = ({ assistant, setActiveTopic }) => { autoFocus contextMenu="true" variant="borderless" - styles={{ textarea: { resize: 'none', paddingLeft: 0 } }} + styles={{ textarea: { paddingLeft: 0 } }} allowClear ref={inputRef} /> diff --git a/src/renderer/src/pages/home/components/Message.tsx b/src/renderer/src/pages/home/components/Message.tsx index da0fc76e..e8caf5c4 100644 --- a/src/renderer/src/pages/home/components/Message.tsx +++ b/src/renderer/src/pages/home/components/Message.tsx @@ -2,12 +2,13 @@ import { Message } from '@renderer/types' import { Avatar, Tooltip } from 'antd' import { FC } from 'react' import styled from 'styled-components' -import Logo from '@renderer/assets/images/logo.png' import useAvatar from '@renderer/hooks/useAvatar' import { CopyOutlined, DeleteOutlined, EditOutlined } from '@ant-design/icons' import Markdown from 'react-markdown' import CodeBlock from './CodeBlock' import { EVENT_NAMES, EventEmitter } from '@renderer/services/event' +import { getModelLogo } from '@renderer/services/provider' +import Logo from '@renderer/assets/images/logo.png' interface Props { message: Message @@ -40,7 +41,13 @@ const MessageItem: FC = ({ message, showMenu, onDeleteMessage }) => { return ( - {message.role === 'assistant' ? : } + + {message.role === 'assistant' ? ( + + ) : ( + + )} + {message.content} diff --git a/src/renderer/src/pages/settings/ModelSettings.tsx b/src/renderer/src/pages/settings/ModelSettings.tsx index a0213e8c..d8b3f68c 100644 --- a/src/renderer/src/pages/settings/ModelSettings.tsx +++ b/src/renderer/src/pages/settings/ModelSettings.tsx @@ -16,7 +16,10 @@ const ModelSettings: FC = () => { .map((p) => ({ label: p.name, title: p.name, - options: p.models.map((m) => ({ label: m.name, value: m.id })) + options: p.models.map((m) => ({ + label: m.name, + value: m.id + })) })) return ( diff --git a/src/renderer/src/pages/settings/ProviderSettings.tsx b/src/renderer/src/pages/settings/ProviderSettings.tsx index ea07e9f0..51415e68 100644 --- a/src/renderer/src/pages/settings/ProviderSettings.tsx +++ b/src/renderer/src/pages/settings/ProviderSettings.tsx @@ -3,6 +3,8 @@ import { Provider } from '@renderer/types' import { FC, useState } from 'react' import styled from 'styled-components' import ModalProviderSetting from './components/ModalProviderSetting' +import { Avatar } from 'antd' +import { getProviderLogo } from '@renderer/services/provider' const ProviderSettings: FC = () => { const providers = useSystemProviders() @@ -16,7 +18,8 @@ const ProviderSettings: FC = () => { key={JSON.stringify(provider)} className={provider.id === selectedProvider?.id ? 'active' : ''} onClick={() => setSelectedProvider(provider)}> - {provider.name} + + {provider.name} ))} @@ -60,4 +63,9 @@ const ProviderListItem = styled.div` } ` +const ProviderItemName = styled.div` + margin-left: 10px; + font-weight: bold; +` + export default ProviderSettings diff --git a/src/renderer/src/pages/settings/components/ModalProviderSetting.tsx b/src/renderer/src/pages/settings/components/ModalProviderSetting.tsx index 937d3fe6..31174beb 100644 --- a/src/renderer/src/pages/settings/components/ModalProviderSetting.tsx +++ b/src/renderer/src/pages/settings/components/ModalProviderSetting.tsx @@ -1,11 +1,12 @@ import { Provider } from '@renderer/types' import { FC, useEffect, useState } from 'react' import styled from 'styled-components' -import { Button, Card, Divider, Input } from 'antd' +import { Avatar, 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' +import { getModelLogo } from '@renderer/services/provider' interface Props { provider: Provider @@ -58,7 +59,10 @@ const ModalProviderSetting: FC = ({ provider }) => { {Object.keys(modelGroups).map((group) => ( {modelGroups[group].map((model) => ( - {model.id} + + + {model.id} + ))} ))} @@ -73,7 +77,7 @@ const ModelListItem = styled.div` display: flex; flex-direction: row; align-items: center; - justify-content: space-between; + justify-content: flex-start; padding: 5px 0; ` diff --git a/src/renderer/src/pages/settings/components/SettingComponent.tsx b/src/renderer/src/pages/settings/components/SettingComponent.tsx index f58779e8..d114a619 100644 --- a/src/renderer/src/pages/settings/components/SettingComponent.tsx +++ b/src/renderer/src/pages/settings/components/SettingComponent.tsx @@ -19,6 +19,7 @@ export const SettingTitle = styled.div` flex-direction: row; justify-content: space-between; align-items: center; + font-weight: 900; ` export const SettingSubtitle = styled.div` diff --git a/src/renderer/src/services/assistant.ts b/src/renderer/src/services/assistant.ts index f7c543cf..e5864e1a 100644 --- a/src/renderer/src/services/assistant.ts +++ b/src/renderer/src/services/assistant.ts @@ -34,7 +34,14 @@ export function getAssistantProvider(assistant: Assistant) { return provider || getDefaultProvider() } -export function getProviderByModel(model: Model) { +export function getProviderByModel(model?: Model) { const providers = store.getState().llm.providers - return providers.find((p) => p.id === model.provider) as Provider + const providerId = model ? model.provider : getDefaultProvider().id + return providers.find((p) => p.id === providerId) as Provider +} + +export function getProviderByModelId(modelId?: string) { + const providers = store.getState().llm.providers + const _modelId = modelId || getDefaultModel().id + return providers.find((p) => p.models.find((m) => m.id === _modelId)) as Provider } diff --git a/src/renderer/src/services/provider.ts b/src/renderer/src/services/provider.ts new file mode 100644 index 00000000..dbd22e5c --- /dev/null +++ b/src/renderer/src/services/provider.ts @@ -0,0 +1,75 @@ +import OpenAiProviderLogo from '@renderer/assets/images/providers/openai.jpeg' +import SiliconFlowProviderLogo from '@renderer/assets/images/providers/silicon.png' +import DeepSeekProviderLogo from '@renderer/assets/images/providers/deepseek.png' +import YiProviderLogo from '@renderer/assets/images/providers/yi.svg' +import GroqProviderLogo from '@renderer/assets/images/providers/groq.png' +import ChatGPTModelLogo from '@renderer/assets/images/models/chatgpt.svg' +import ChatGLMModelLogo from '@renderer/assets/images/models/chatglm.jpeg' +import DeepSeekModelLogo from '@renderer/assets/images/models/deepseek.png' +import GemmaModelLogo from '@renderer/assets/images/models/gemma.jpeg' +import QwenModelLogo from '@renderer/assets/images/models/qwen.jpeg' +import YiModelLogo from '@renderer/assets/images/models/yi.svg' +import LlamaModelLogo from '@renderer/assets/images/models/llama.jpeg' +import MixtralModelLogo from '@renderer/assets/images/models/mixtral.jpeg' + +export function getProviderLogo(providerId: string) { + if (providerId === 'openai') { + return OpenAiProviderLogo + } + + if (providerId === 'silicon') { + return SiliconFlowProviderLogo + } + + if (providerId === 'deepseek') { + return DeepSeekProviderLogo + } + + if (providerId === 'yi') { + return YiProviderLogo + } + + if (providerId === 'groq') { + return GroqProviderLogo + } + + return '' +} + +export function getModelLogo(modelId: string) { + const _modelId = modelId.toLowerCase() + + if (_modelId.includes('gpt')) { + return ChatGPTModelLogo + } + + if (_modelId.includes('glm')) { + return ChatGLMModelLogo + } + + if (_modelId.includes('deepseek')) { + return DeepSeekModelLogo + } + + if (_modelId.includes('qwen')) { + return QwenModelLogo + } + + if (_modelId.includes('gemma')) { + return GemmaModelLogo + } + + if (_modelId.includes('yi-')) { + return YiModelLogo + } + + if (_modelId.includes('llama')) { + return LlamaModelLogo + } + + if (_modelId.includes('mixtral')) { + return MixtralModelLogo + } + + return '' +}