feat: update input component and add translation features

This commit is contained in:
kangfenmao 2024-11-25 13:24:36 +08:00
parent 603b867a5f
commit dcf57651fe
12 changed files with 94 additions and 22 deletions

View File

@ -1,4 +1,5 @@
import { Input, InputProps, Modal } from 'antd'
import { Input, Modal } from 'antd'
import { TextAreaProps } from 'antd/es/input'
import { useState } from 'react'
import { Box } from '../Layout'
@ -9,7 +10,7 @@ interface PromptPopupShowParams {
message: string
defaultValue?: string
inputPlaceholder?: string
inputProps?: InputProps
inputProps?: TextAreaProps
}
interface Props extends PromptPopupShowParams {
@ -42,13 +43,14 @@ const PromptPopupContainer: React.FC<Props> = ({
return (
<Modal title={title} open={open} onOk={onOk} onCancel={handleCancel} afterClose={onClose} centered>
<Box mb={8}>{message}</Box>
<Input
<Input.TextArea
placeholder={inputPlaceholder}
value={value}
onChange={(e) => setValue(e.target.value)}
allowClear
autoFocus
onPressEnter={onOk}
rows={1}
{...inputProps}
/>
</Modal>

View File

@ -46,3 +46,6 @@ export const AGENT_PROMPT = `
export const SUMMARIZE_PROMPT =
'你是一名擅长会话的助理,你需要将用户的会话总结为 10 个字以内的标题,不要使用标点符号和其他特殊符号。'
export const TRANSLATE_PROMPT =
'Translate from input language to {{target_language}}, provide the translation result directly without any explanation, keep original format. If the target language is the same as the source language, do not translate. The text to be translated is as follows:\n\n{{text}}'

View File

@ -32,7 +32,8 @@
"chat": "Chat",
"close": "Close",
"cancel": "Cancel",
"download": "Download"
"download": "Download",
"reset": "Reset"
},
"button": {
"add": "Add",
@ -312,6 +313,8 @@
"models.add.group_name": "Group Name",
"models.add.group_name.tooltip": "Optional e.g. ChatGPT",
"models.add.group_name.placeholder": "Optional e.g. ChatGPT",
"models.translate_model_prompt_title": "Translate Model Prompt",
"models.translate_model_prompt_message": "Please enter the translate model prompt",
"models.empty": "No models found",
"assistant.title": "Default Assistant",
"assistant.model_params": "Model Parameters",

View File

@ -32,7 +32,8 @@
"chat": "Чат",
"close": "Закрыть",
"cancel": "Отмена",
"download": "Скачать"
"download": "Скачать",
"reset": "Сбросить"
},
"button": {
"add": "Добавить",
@ -312,6 +313,8 @@
"models.add.group_name": "Имя группы",
"models.add.group_name.tooltip": "Необязательно, например, ChatGPT",
"models.add.group_name.placeholder": "Необязательно, например, ChatGPT",
"models.translate_model_prompt_title": "Модель перевода",
"models.translate_model_prompt_message": "Введите модель перевода",
"models.empty": "Модели не найдены",
"assistant.title": "Ассистент по умолчанию",
"assistant.model_params": "Параметры модели",

View File

@ -32,7 +32,8 @@
"chat": "聊天",
"close": "关闭",
"cancel": "取消",
"download": "下载"
"download": "下载",
"reset": "重置"
},
"button": {
"add": "添加",
@ -300,6 +301,8 @@
"models.add.group_name": "分组名称",
"models.add.group_name.tooltip": "例如 ChatGPT",
"models.add.group_name.placeholder": "例如 ChatGPT",
"models.translate_model_prompt_title": "翻译模型提示词",
"models.translate_model_prompt_message": "请输入翻译模型提示词",
"models.empty": "没有模型",
"assistant.title": "默认助手",
"assistant.model_params": "模型参数",

View File

@ -32,7 +32,8 @@
"chat": "聊天",
"close": "關閉",
"cancel": "取消",
"download": "下載"
"download": "下載",
"reset": "重置"
},
"button": {
"add": "添加",
@ -300,6 +301,8 @@
"models.add.group_name": "群組名稱",
"models.add.group_name.tooltip": "可選,例如 ChatGPT",
"models.add.group_name.placeholder": "可選,例如 ChatGPT",
"models.translate_model_prompt_title": "翻譯模型提示詞",
"models.translate_model_prompt_message": "請輸入翻譯模型提示詞",
"models.empty": "找不到模型",
"assistant.title": "預設助手",
"assistant.model_params": "模型參數",

View File

@ -1,11 +1,16 @@
import { EditOutlined, MessageOutlined, SettingOutlined, TranslationOutlined } from '@ant-design/icons'
import { EditOutlined, MessageOutlined, RedoOutlined, SettingOutlined, TranslationOutlined } from '@ant-design/icons'
import { HStack } from '@renderer/components/Layout'
import PromptPopup from '@renderer/components/Popups/PromptPopup'
import { TRANSLATE_PROMPT } from '@renderer/config/prompts'
import { useTheme } from '@renderer/context/ThemeProvider'
import { useDefaultModel } from '@renderer/hooks/useAssistant'
import { useProviders } from '@renderer/hooks/useProvider'
import { useSettings } from '@renderer/hooks/useSettings'
import { getModelUniqId, hasModel } from '@renderer/services/ModelService'
import { useAppDispatch } from '@renderer/store'
import { setTranslateModelPrompt } from '@renderer/store/settings'
import { Model } from '@renderer/types'
import { Button, Select } from 'antd'
import { Button, Select, Tooltip } from 'antd'
import { find, sortBy } from 'lodash'
import { FC, useMemo } from 'react'
import { useTranslation } from 'react-i18next'
@ -20,6 +25,9 @@ const ModelSettings: FC = () => {
const allModels = providers.map((p) => p.models).flat()
const { theme } = useTheme()
const { t } = useTranslation()
const { translateModelPrompt } = useSettings()
const dispatch = useAppDispatch()
const selectOptions = providers
.filter((p) => p.models.length > 0)
@ -47,6 +55,24 @@ const ModelSettings: FC = () => {
[translateModel]
)
const onUpdateTranslateModel = async () => {
const prompt = await PromptPopup.show({
title: t('settings.models.translate_model_prompt_title'),
message: t('settings.models.translate_model_prompt_message'),
defaultValue: translateModelPrompt,
inputProps: {
rows: 10
}
})
if (prompt) {
dispatch(setTranslateModelPrompt(prompt))
}
}
const onResetTranslatePrompt = () => {
dispatch(setTranslateModelPrompt(TRANSLATE_PROMPT))
}
return (
<SettingContainer theme={theme}>
<SettingGroup theme={theme}>
@ -93,6 +119,7 @@ const ModelSettings: FC = () => {
{t('settings.models.translate_model')}
</div>
</SettingTitle>
<HStack alignItems="center">
<Select
value={defaultTranslateModel}
defaultValue={defaultTranslateModel}
@ -101,6 +128,13 @@ const ModelSettings: FC = () => {
options={selectOptions}
placeholder={t('settings.models.empty')}
/>
<Button icon={<SettingOutlined />} style={{ marginLeft: 8 }} onClick={onUpdateTranslateModel} />
{translateModelPrompt !== TRANSLATE_PROMPT && (
<Tooltip title={t('common.reset')}>
<Button icon={<RedoOutlined />} style={{ marginLeft: 8 }} onClick={onResetTranslatePrompt}></Button>
</Tooltip>
)}
</HStack>
<SettingDescription>{t('settings.models.translate_model_description')}</SettingDescription>
</SettingGroup>
</SettingContainer>

View File

@ -11,7 +11,7 @@ import VisionIcon from '@renderer/components/Icons/VisionIcon'
import { getModelLogo, isVisionModel, VISION_REGEX } from '@renderer/config/models'
import { PROVIDER_CONFIG } from '@renderer/config/providers'
import { useTheme } from '@renderer/context/ThemeProvider'
import { useAssistants } from '@renderer/hooks/useAssistant'
import { useAssistants, useDefaultModel } from '@renderer/hooks/useAssistant'
import { useProvider } from '@renderer/hooks/useProvider'
import i18n from '@renderer/i18n'
import { isOpenAIProvider } from '@renderer/providers/ProviderFactory'
@ -57,6 +57,8 @@ const ProviderSetting: FC<Props> = ({ provider: _provider }) => {
const { theme } = useTheme()
const dispatch = useAppDispatch()
const { defaultModel, setDefaultModel } = useDefaultModel()
const modelGroups = groupBy(models, 'group')
useEffect(() => {
@ -151,6 +153,10 @@ const ProviderSetting: FC<Props> = ({ provider: _provider }) => {
)
}
})
if (defaultModel?.id === model.id && defaultModel?.provider === provider.id) {
setDefaultModel({ ...defaultModel, type: types })
}
}
const modelTypeContent = (model: Model) => (

View File

@ -23,7 +23,10 @@ export function getDefaultTranslateAssistant(targetLanguage: string, text: strin
const translateModel = getTranslateModel()
const assistant: Assistant = getDefaultAssistant()
assistant.model = translateModel
assistant.prompt = `Translate from input language to ${targetLanguage}, provide the translation result directly without any explanation, keep original format. If the target language is the same as the source language, do not translate. The text to be translated is as follows:\n\n ${text}`
assistant.prompt = store
.getState()
.settings.translateModelPrompt.replace('{{target_language}}', targetLanguage)
.replace('{{text}}', text)
return assistant
}

View File

@ -24,7 +24,7 @@ const persistedReducer = persistReducer(
{
key: 'cherry-studio',
storage,
version: 43,
version: 44,
blacklist: ['runtime'],
migrate
},

View File

@ -1,4 +1,5 @@
import { SYSTEM_MODELS } from '@renderer/config/models'
import { TRANSLATE_PROMPT } from '@renderer/config/prompts'
import db from '@renderer/databases'
import i18n from '@renderer/i18n'
import { Assistant } from '@renderer/types'
@ -699,6 +700,10 @@ const migrateConfig = {
state.settings.proxyMode = 'system'
}
return state
},
'44': (state: RootState) => {
state.settings.translateModelPrompt = TRANSLATE_PROMPT
return state
}
}

View File

@ -1,4 +1,5 @@
import { createSlice, PayloadAction } from '@reduxjs/toolkit'
import { TRANSLATE_PROMPT } from '@renderer/config/prompts'
import { CodeStyleVarious, LanguageVarious, ThemeMode } from '@renderer/types'
export type SendMessageShortcut = 'Enter' | 'Shift+Enter'
@ -34,6 +35,7 @@ export interface SettingsState {
webdavUser: string
webdavPass: string
webdavPath: string
translateModelPrompt: string
}
const initialState: SettingsState = {
@ -65,7 +67,8 @@ const initialState: SettingsState = {
webdavHost: '',
webdavUser: '',
webdavPass: '',
webdavPath: '/cherry-studio'
webdavPath: '/cherry-studio',
translateModelPrompt: TRANSLATE_PROMPT
}
const settingsSlice = createSlice({
@ -165,6 +168,9 @@ const settingsSlice = createSlice({
},
setCodeStyle: (state, action: PayloadAction<CodeStyleVarious>) => {
state.codeStyle = action.payload
},
setTranslateModelPrompt: (state, action: PayloadAction<string>) => {
state.translateModelPrompt = action.payload
}
}
})
@ -200,7 +206,8 @@ export const {
setCodeCollapsible,
setMathEngine,
setMessageStyle,
setCodeStyle
setCodeStyle,
setTranslateModelPrompt
} = settingsSlice.actions
export default settingsSlice.reducer