mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2025-12-25 11:20:07 +08:00
feat: add localization text and model type support #378
This commit is contained in:
parent
d377376bae
commit
1e2ebe5232
@ -1,15 +1,15 @@
|
||||
:root {
|
||||
--color-scrollbar-thumb: rgba(255, 255, 255, 0.15);
|
||||
--color-scrollbar-thumb-hover: rgba(255, 255, 255, 0.2);
|
||||
--color-scrollbar-thumb-right: rgba(255, 255, 255, 0.25);
|
||||
--color-scrollbar-thumb-right-hover: rgba(255, 255, 255, 0.35);
|
||||
--color-scrollbar-thumb-right: rgba(255, 255, 255, 0.18);
|
||||
--color-scrollbar-thumb-right-hover: rgba(255, 255, 255, 0.25);
|
||||
}
|
||||
|
||||
body[theme-mode='light'] {
|
||||
--color-scrollbar-thumb: rgba(0, 0, 0, 0.15);
|
||||
--color-scrollbar-thumb-hover: rgba(0, 0, 0, 0.2);
|
||||
--color-scrollbar-thumb-right: rgba(0, 0, 0, 0.25);
|
||||
--color-scrollbar-thumb-right-hover: rgba(0, 0, 0, 0.35);
|
||||
--color-scrollbar-thumb-right: rgba(0, 0, 0, 0.18);
|
||||
--color-scrollbar-thumb-right-hover: rgba(0, 0, 0, 0.25);
|
||||
}
|
||||
|
||||
/* 全局初始化滚动条样式 */
|
||||
|
||||
@ -145,7 +145,7 @@ const visionAllowedModels = [
|
||||
|
||||
const visionExcludedModels = ['gpt-4-\\d+-preview', 'gpt-4-turbo-preview', 'gpt-4-32k', 'gpt-4-\\d+']
|
||||
|
||||
const VISION_REGEX = new RegExp(
|
||||
export const VISION_REGEX = new RegExp(
|
||||
`\\b(?!(?:${visionExcludedModels.join('|')})\\b)(${visionAllowedModels.join('|')})\\b`,
|
||||
'i'
|
||||
)
|
||||
@ -1044,7 +1044,7 @@ export function isEmbeddingModel(model: Model): boolean {
|
||||
}
|
||||
|
||||
export function isVisionModel(model: Model): boolean {
|
||||
return VISION_REGEX.test(model.id)
|
||||
return VISION_REGEX.test(model.id) || model.type?.includes('vision') || false
|
||||
}
|
||||
|
||||
export function isSupportedModel(model: OpenAI.Models.Model): boolean {
|
||||
|
||||
@ -145,7 +145,12 @@
|
||||
"model": {
|
||||
"stream_output": "Stream Output",
|
||||
"search": "Search models...",
|
||||
"pinned": "Pinned"
|
||||
"pinned": "Pinned",
|
||||
"type": {
|
||||
"text": "Text",
|
||||
"vision": "Vision",
|
||||
"select": "Select Model Types"
|
||||
}
|
||||
},
|
||||
"paintings": {
|
||||
"title": "Images",
|
||||
|
||||
@ -145,7 +145,12 @@
|
||||
"model": {
|
||||
"stream_output": "Потоковый вывод",
|
||||
"search": "Поиск моделей...",
|
||||
"pinned": "Закреплено"
|
||||
"pinned": "Закреплено",
|
||||
"type": {
|
||||
"text": "Текст",
|
||||
"vision": "Изображение",
|
||||
"select": "Выберите тип модели"
|
||||
}
|
||||
},
|
||||
"paintings": {
|
||||
"title": "Изображения",
|
||||
|
||||
@ -145,7 +145,12 @@
|
||||
"model": {
|
||||
"stream_output": "流式输出",
|
||||
"search": "搜索模型...",
|
||||
"pinned": "已固定"
|
||||
"pinned": "已固定",
|
||||
"type": {
|
||||
"text": "文本",
|
||||
"vision": "图像",
|
||||
"select": "选择模型类型"
|
||||
}
|
||||
},
|
||||
"paintings": {
|
||||
"title": "图片",
|
||||
@ -316,7 +321,7 @@
|
||||
"about.title": "关于我们",
|
||||
"about.releases.title": "更新日志",
|
||||
"about.releases.button": "查看",
|
||||
"about.website.title": "官方网站",
|
||||
"about.website.title": "官方网<EFBFBD><EFBFBD><EFBFBD>",
|
||||
"about.website.button": "查看",
|
||||
"about.feedback.title": "意见反馈",
|
||||
"about.feedback.button": "反馈",
|
||||
|
||||
@ -145,7 +145,12 @@
|
||||
"model": {
|
||||
"stream_output": "串流輸出",
|
||||
"search": "搜尋模型...",
|
||||
"pinned": "已固定"
|
||||
"pinned": "已固定",
|
||||
"type": {
|
||||
"text": "文字",
|
||||
"vision": "圖像",
|
||||
"select": "選擇模型類型"
|
||||
}
|
||||
},
|
||||
"paintings": {
|
||||
"title": "繪圖",
|
||||
@ -431,7 +436,7 @@
|
||||
"user": "用戶",
|
||||
"assistant": "助手",
|
||||
"created": "創建時間",
|
||||
"last_updated": "最後更新",
|
||||
"last_updated": "最後<EFBFBD><EFBFBD>新",
|
||||
"messages": "訊息數",
|
||||
"conversation_details": "會話詳情",
|
||||
"conversation_history": "會話歷史"
|
||||
|
||||
@ -4,18 +4,19 @@ import {
|
||||
ExportOutlined,
|
||||
LoadingOutlined,
|
||||
MinusCircleOutlined,
|
||||
PlusOutlined
|
||||
PlusOutlined,
|
||||
SettingOutlined
|
||||
} from '@ant-design/icons'
|
||||
import VisionIcon from '@renderer/components/Icons/VisionIcon'
|
||||
import { getModelLogo, isVisionModel } from '@renderer/config/models'
|
||||
import { getModelLogo, isVisionModel, VISION_REGEX } from '@renderer/config/models'
|
||||
import { PROVIDER_CONFIG } from '@renderer/config/providers'
|
||||
import { useTheme } from '@renderer/context/ThemeProvider'
|
||||
import { useProvider } from '@renderer/hooks/useProvider'
|
||||
import i18n from '@renderer/i18n'
|
||||
import { isOpenAIProvider } from '@renderer/providers/ProviderFactory'
|
||||
import { checkApi } from '@renderer/services/ApiService'
|
||||
import { Provider } from '@renderer/types'
|
||||
import { Avatar, Button, Card, Divider, Flex, Input, Space, Switch } from 'antd'
|
||||
import { Model, ModelType, Provider } from '@renderer/types'
|
||||
import { Avatar, Button, Card, Checkbox, Divider, Flex, Input, Popover, Space, Switch } from 'antd'
|
||||
import Link from 'antd/es/typography/Link'
|
||||
import { groupBy, isEmpty } from 'lodash'
|
||||
import { FC, useEffect, useState } from 'react'
|
||||
@ -125,6 +126,26 @@ const ProviderSetting: FC<Props> = ({ provider: _provider }) => {
|
||||
return (apiHost.endsWith('/') ? apiHost : `${apiHost}/v1/`) + 'chat/completions'
|
||||
}
|
||||
|
||||
const onUpdateModelTypes = (model: Model, types: ModelType[]) => {
|
||||
const updatedModels = models.map((m) => {
|
||||
if (m.id === model.id) {
|
||||
return { ...m, type: types }
|
||||
}
|
||||
return m
|
||||
})
|
||||
updateProvider({ ...provider, models: updatedModels })
|
||||
}
|
||||
|
||||
const modelTypeContent = (model: Model) => (
|
||||
<div>
|
||||
<Checkbox.Group
|
||||
value={model.type}
|
||||
onChange={(types) => onUpdateModelTypes(model, types as ModelType[])}
|
||||
options={[{ label: t('model.type.vision'), value: 'vision', disabled: VISION_REGEX.test(model.id) }]}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
|
||||
return (
|
||||
<SettingContainer theme={theme}>
|
||||
<SettingTitle>
|
||||
@ -211,6 +232,9 @@ const ProviderSetting: FC<Props> = ({ provider: _provider }) => {
|
||||
{model.name[0].toUpperCase()}
|
||||
</Avatar>
|
||||
{model.name} {isVisionModel(model) && <VisionIcon />}
|
||||
<Popover content={modelTypeContent(model)} title={t('model.type.select')} trigger="click">
|
||||
<SettingIcon />
|
||||
</Popover>
|
||||
</ModelListHeader>
|
||||
<RemoveIcon onClick={() => removeModel(model)} />
|
||||
</ModelListItem>
|
||||
@ -265,4 +289,14 @@ const RemoveIcon = styled(MinusCircleOutlined)`
|
||||
transition: all 0.2s ease-in-out;
|
||||
`
|
||||
|
||||
const SettingIcon = styled(SettingOutlined)`
|
||||
margin-left: 10px;
|
||||
color: var(--color-text);
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease-in-out;
|
||||
&:hover {
|
||||
color: var(--color-text-2);
|
||||
}
|
||||
`
|
||||
|
||||
export default ProviderSetting
|
||||
|
||||
@ -78,6 +78,8 @@ export type Provider = {
|
||||
|
||||
export type ProviderType = 'openai' | 'anthropic' | 'gemini'
|
||||
|
||||
export type ModelType = 'text' | 'vision'
|
||||
|
||||
export type Model = {
|
||||
id: string
|
||||
provider: string
|
||||
@ -85,6 +87,7 @@ export type Model = {
|
||||
group: string
|
||||
owned_by?: string
|
||||
description?: string
|
||||
type?: ModelType[]
|
||||
}
|
||||
|
||||
export type Suggestion = {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user