mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2025-12-24 18:50:56 +08:00
feat: add quick assistant settings panel and management functionality (#6201)
* feat: add quick assistant settings panel and management functionality - Create QuickAssistantSettings component for UI - Extend useAssistant hook with quick assistant controls - Add settings button in ModelSettings page - Implement temperature, context count, max tokens, and other parameters - Connect settings to store via updateQuickAssistant action Separate quick assistant preferences from default assistant settings for better customization. * refactor(QuickAssistantSettings): remove maxTokens and refine UI layout - Removed maxTokens related state, logic, and UI elements - Simplified settings page by eliminating unused configuration - Adjusted layout for Slider and InputNumber for better usability - Removed fixed width from Modal to enable responsive behavior * refactor(HomeWindow): optimize message building logic - Removed redundant quickAssistant fetching logic - Use `useQuickAssistant` hook directly for cleaner code - Simplified message content concatenation method * style(QuickAssistantSettings): Adjust spacing in settings page layout Change the column width of sliders and input fields from 20/4 to 21/3 for a more reasonable layout Also set the popup width to 800px to improve user experience * feat(Quick Assistant): Add option to select assistant or model, and optimize Quick Assistant logic - Added functionality to choose between using models or referencing other assistants - Optimized model selection logic to automatically select based on settings - Added relevant internationalization texts * fix(HomeWindow): Dynamically display input box placeholder text based on quick assistant states * refactor(QuickAssistant): remove the implement of the quick assistant feature and restructure related logic - Remove code related to the quick assistant feature, including the useQuickAssistant hook, QuickAssistantSettings component, and associated store logic. - Restructure the HomeWindow component to use default or specified assistants instead of the quick assistant functionality, simplifying the code structure. * refactor(QuickAssistant): Remove custom default model for quick assistant and switch to default assistant - Refactor quick assistant functionality, remove independent model settings, change to select via assistant ID - Update multilingual translation text to match new features * refactor(QuickAssistant): Remove quick assistant-related states and simplify logic - Remove unused quick assistant states and toggle functionality, simplifying related logic - Update multilingual files to match the new default model and assistant labels * refactor(i18n): Unify translation keys for input field placeholders Unify the placeholder translation keys from `model_empty` and `assistant_empty` into empty across different scenarios, streamlining code logic * refactor(settings): simplify quick helper selection logic by directly using the preset helper - Removed redundant helper filtering logic, directly using the preset helper as the quick helper
This commit is contained in:
parent
9faa45b571
commit
477b5d2449
@ -15,7 +15,7 @@ import {
|
||||
updateTopic,
|
||||
updateTopics
|
||||
} from '@renderer/store/assistants'
|
||||
import { setDefaultModel, setQuickAssistantModel, setTopicNamingModel, setTranslateModel } from '@renderer/store/llm'
|
||||
import { setDefaultModel, setTopicNamingModel, setTranslateModel } from '@renderer/store/llm'
|
||||
import { Assistant, AssistantSettings, Model, Topic } from '@renderer/types'
|
||||
import { useCallback, useMemo } from 'react'
|
||||
|
||||
@ -103,17 +103,15 @@ export function useDefaultAssistant() {
|
||||
}
|
||||
|
||||
export function useDefaultModel() {
|
||||
const { defaultModel, topicNamingModel, translateModel, quickAssistantModel } = useAppSelector((state) => state.llm)
|
||||
const { defaultModel, topicNamingModel, translateModel } = useAppSelector((state) => state.llm)
|
||||
const dispatch = useAppDispatch()
|
||||
|
||||
return {
|
||||
defaultModel,
|
||||
topicNamingModel,
|
||||
translateModel,
|
||||
quickAssistantModel,
|
||||
setDefaultModel: (model: Model) => dispatch(setDefaultModel({ model })),
|
||||
setTopicNamingModel: (model: Model) => dispatch(setTopicNamingModel({ model })),
|
||||
setTranslateModel: (model: Model) => dispatch(setTranslateModel({ model })),
|
||||
setQuickAssistantModel: (model: Model) => dispatch(setQuickAssistantModel({ model }))
|
||||
setTranslateModel: (model: Model) => dispatch(setTranslateModel({ model }))
|
||||
}
|
||||
}
|
||||
|
||||
@ -1592,6 +1592,10 @@
|
||||
"models.translate_model_prompt_title": "Translate Model Prompt",
|
||||
"models.quick_assistant_model": "Quick Assistant Model",
|
||||
"models.quick_assistant_model_description": "Default model used by Quick Assistant",
|
||||
"models.quick_assistant_selection": "Select Assistant",
|
||||
"models.quick_assistant_default_tag": "Default",
|
||||
"models.use_model": "Default Model",
|
||||
"models.use_assistant": "Use Assistant",
|
||||
"moresetting": "More Settings",
|
||||
"moresetting.check.confirm": "Confirm Selection",
|
||||
"moresetting.check.warn": "Please be cautious when selecting this option. Incorrect selection may cause the model to malfunction!",
|
||||
|
||||
@ -1586,6 +1586,10 @@
|
||||
"models.translate_model_prompt_title": "翻訳モデルのプロンプト",
|
||||
"models.quick_assistant_model": "クイックアシスタントモデル",
|
||||
"models.quick_assistant_model_description": "クイックアシスタントで使用されるデフォルトモデル",
|
||||
"models.quick_assistant_selection": "アシスタントを選択します",
|
||||
"models.quick_assistant_default_tag": "デフォルト",
|
||||
"models.use_model": "デフォルトモデル",
|
||||
"models.use_assistant": "アシスタントの活用",
|
||||
"moresetting": "詳細設定",
|
||||
"moresetting.check.confirm": "選択を確認",
|
||||
"moresetting.check.warn": "このオプションを選択する際は慎重に行ってください。誤った選択はモデルの誤動作を引き起こす可能性があります!",
|
||||
|
||||
@ -1586,6 +1586,10 @@
|
||||
"models.translate_model_prompt_title": "Модель перевода",
|
||||
"models.quick_assistant_model": "Модель быстрого помощника",
|
||||
"models.quick_assistant_model_description": "Модель по умолчанию, используемая быстрым помощником",
|
||||
"models.quick_assistant_selection": "Выберите помощника",
|
||||
"models.quick_assistant_default_tag": "умолчанию",
|
||||
"models.use_model": "модель по умолчанию",
|
||||
"models.use_assistant": "Использование ассистентов",
|
||||
"moresetting": "Дополнительные настройки",
|
||||
"moresetting.check.confirm": "Подтвердить выбор",
|
||||
"moresetting.check.warn": "Пожалуйста, будьте осторожны при выборе этой опции. Неправильный выбор может привести к сбою в работе модели!",
|
||||
|
||||
@ -1592,6 +1592,10 @@
|
||||
"models.translate_model_prompt_title": "翻译模型提示词",
|
||||
"models.quick_assistant_model": "快捷助手模型",
|
||||
"models.quick_assistant_model_description": "快捷助手使用的默认模型",
|
||||
"models.quick_assistant_selection": "选择助手",
|
||||
"models.quick_assistant_default_tag": "默认",
|
||||
"models.use_model": "默认模型",
|
||||
"models.use_assistant": "使用助手",
|
||||
"moresetting": "更多设置",
|
||||
"moresetting.check.confirm": "确认勾选",
|
||||
"moresetting.check.warn": "请慎重勾选此选项,勾选错误会导致模型无法正常使用!!!",
|
||||
|
||||
@ -1589,6 +1589,10 @@
|
||||
"models.translate_model_prompt_title": "翻譯模型提示詞",
|
||||
"models.quick_assistant_model": "快捷助手模型",
|
||||
"models.quick_assistant_model_description": "快捷助手使用的預設模型",
|
||||
"models.quick_assistant_selection": "選擇助手",
|
||||
"models.quick_assistant_default_tag": "預設",
|
||||
"models.use_model": "預設模型",
|
||||
"models.use_assistant": "使用助手",
|
||||
"moresetting": "更多設定",
|
||||
"moresetting.check.confirm": "確認勾選",
|
||||
"moresetting.check.warn": "請謹慎勾選此選項,勾選錯誤會導致模型無法正常使用!!!",
|
||||
@ -1957,7 +1961,7 @@
|
||||
},
|
||||
"opacity": {
|
||||
"title": "透明度",
|
||||
"description": "設置視窗的默認透明度,100%為完全不透明"
|
||||
"description": "設置視窗的預設透明度,100%為完全不透明"
|
||||
}
|
||||
},
|
||||
"actions": {
|
||||
|
||||
@ -1,37 +1,35 @@
|
||||
import { RedoOutlined } from '@ant-design/icons'
|
||||
import ModelAvatar from '@renderer/components/Avatar/ModelAvatar'
|
||||
import { HStack } from '@renderer/components/Layout'
|
||||
import PromptPopup from '@renderer/components/Popups/PromptPopup'
|
||||
import { isEmbeddingModel } from '@renderer/config/models'
|
||||
import { TRANSLATE_PROMPT } from '@renderer/config/prompts'
|
||||
import { useTheme } from '@renderer/context/ThemeProvider'
|
||||
import { useDefaultModel } from '@renderer/hooks/useAssistant'
|
||||
import { useAssistants, useDefaultAssistant, 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 { useAppSelector } from '@renderer/store'
|
||||
import { useAppDispatch } from '@renderer/store'
|
||||
import { setQuickAssistantId } from '@renderer/store/llm'
|
||||
import { setTranslateModelPrompt } from '@renderer/store/settings'
|
||||
import { Model } from '@renderer/types'
|
||||
import { Button, Select, Tooltip } from 'antd'
|
||||
import { find, sortBy } from 'lodash'
|
||||
import { FolderPen, Languages, MessageSquareMore, Rocket, Settings2 } from 'lucide-react'
|
||||
import { CircleHelp, FolderPen, Languages, MessageSquareMore, Rocket, Settings2 } from 'lucide-react'
|
||||
import { FC, useMemo } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import styled from 'styled-components'
|
||||
|
||||
import { SettingContainer, SettingDescription, SettingGroup, SettingTitle } from '..'
|
||||
import DefaultAssistantSettings from './DefaultAssistantSettings'
|
||||
import TopicNamingModalPopup from './TopicNamingModalPopup'
|
||||
|
||||
const ModelSettings: FC = () => {
|
||||
const {
|
||||
defaultModel,
|
||||
topicNamingModel,
|
||||
translateModel,
|
||||
quickAssistantModel,
|
||||
setDefaultModel,
|
||||
setTopicNamingModel,
|
||||
setTranslateModel,
|
||||
setQuickAssistantModel
|
||||
} = useDefaultModel()
|
||||
const { defaultModel, topicNamingModel, translateModel, setDefaultModel, setTopicNamingModel, setTranslateModel } =
|
||||
useDefaultModel()
|
||||
const { defaultAssistant } = useDefaultAssistant()
|
||||
const { assistants } = useAssistants()
|
||||
const { providers } = useProviders()
|
||||
const allModels = providers.map((p) => p.models).flat()
|
||||
const { theme } = useTheme()
|
||||
@ -39,6 +37,7 @@ const ModelSettings: FC = () => {
|
||||
const { translateModelPrompt } = useSettings()
|
||||
|
||||
const dispatch = useAppDispatch()
|
||||
const { quickAssistantId } = useAppSelector((state) => state.llm)
|
||||
|
||||
const selectOptions = providers
|
||||
.filter((p) => p.models.length > 0)
|
||||
@ -68,11 +67,6 @@ const ModelSettings: FC = () => {
|
||||
[translateModel]
|
||||
)
|
||||
|
||||
const defaultQuickAssistantModel = useMemo(
|
||||
() => (hasModel(quickAssistantModel) ? getModelUniqId(quickAssistantModel) : undefined),
|
||||
[quickAssistantModel]
|
||||
)
|
||||
|
||||
const onUpdateTranslateModel = async () => {
|
||||
const prompt = await PromptPopup.show({
|
||||
title: t('settings.models.translate_model_prompt_title'),
|
||||
@ -163,27 +157,118 @@ const ModelSettings: FC = () => {
|
||||
<SettingDescription>{t('settings.models.translate_model_description')}</SettingDescription>
|
||||
</SettingGroup>
|
||||
<SettingGroup theme={theme}>
|
||||
<SettingTitle style={{ marginBottom: 12 }}>
|
||||
<HStack alignItems="center" gap={10}>
|
||||
<Rocket size={18} color="var(--color-text)" />
|
||||
{t('settings.models.quick_assistant_model')}
|
||||
</HStack>
|
||||
</SettingTitle>
|
||||
<HStack alignItems="center">
|
||||
<Select
|
||||
value={defaultQuickAssistantModel}
|
||||
defaultValue={defaultQuickAssistantModel}
|
||||
style={{ width: 360 }}
|
||||
onChange={(value) => setQuickAssistantModel(find(allModels, JSON.parse(value)) as Model)}
|
||||
options={selectOptions}
|
||||
showSearch
|
||||
placeholder={t('settings.models.empty')}
|
||||
/>
|
||||
<HStack alignItems="center" style={{ marginBottom: 12 }}>
|
||||
<SettingTitle>
|
||||
<HStack alignItems="center" gap={10}>
|
||||
<Rocket size={18} color="var(--color-text)" />
|
||||
{t('settings.models.quick_assistant_model')}
|
||||
<Tooltip title={t('selection.settings.user_modal.model.tooltip')} arrow>
|
||||
<QuestionIcon size={12} />
|
||||
</Tooltip>
|
||||
<Spacer />
|
||||
</HStack>
|
||||
<HStack alignItems="center" gap={0}>
|
||||
<StyledButton
|
||||
type={!quickAssistantId ? 'primary' : 'default'}
|
||||
onClick={() => dispatch(setQuickAssistantId(null))}
|
||||
selected={!quickAssistantId}>
|
||||
{t('settings.models.use_model')}
|
||||
</StyledButton>
|
||||
<StyledButton
|
||||
type={quickAssistantId ? 'primary' : 'default'}
|
||||
onClick={() => {
|
||||
dispatch(setQuickAssistantId(defaultAssistant.id))
|
||||
}}
|
||||
selected={!!quickAssistantId}>
|
||||
{t('settings.models.use_assistant')}
|
||||
</StyledButton>
|
||||
</HStack>
|
||||
</SettingTitle>
|
||||
</HStack>
|
||||
{!quickAssistantId ? null : (
|
||||
<HStack alignItems="center" style={{ marginTop: 12 }}>
|
||||
<Select
|
||||
value={quickAssistantId}
|
||||
style={{ width: 360 }}
|
||||
onChange={(value) => dispatch(setQuickAssistantId(value))}
|
||||
placeholder={t('settings.models.quick_assistant_selection')}>
|
||||
{assistants.map((a) => (
|
||||
<Select.Option key={a.id} value={a.id}>
|
||||
<AssistantItem>
|
||||
<ModelAvatar model={a.model || defaultModel} size={18} />
|
||||
<AssistantName>{a.name}</AssistantName>
|
||||
<Spacer />
|
||||
{a.id === defaultAssistant.id && (
|
||||
<DefaultTag isCurrent={true}>{t('settings.models.quick_assistant_default_tag')}</DefaultTag>
|
||||
)}
|
||||
</AssistantItem>
|
||||
</Select.Option>
|
||||
))}
|
||||
</Select>
|
||||
</HStack>
|
||||
)}
|
||||
<SettingDescription>{t('settings.models.quick_assistant_model_description')}</SettingDescription>
|
||||
</SettingGroup>
|
||||
</SettingContainer>
|
||||
)
|
||||
}
|
||||
|
||||
const QuestionIcon = styled(CircleHelp)`
|
||||
cursor: pointer;
|
||||
color: var(--color-text-3);
|
||||
`
|
||||
|
||||
const StyledButton = styled(Button)<{ selected: boolean }>`
|
||||
border-radius: ${(props) => (props.selected ? '6px' : '6px')};
|
||||
z-index: ${(props) => (props.selected ? 1 : 0)};
|
||||
min-width: 80px;
|
||||
|
||||
&:first-child {
|
||||
border-top-right-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
border-right-width: 0px; // No right border for the first button when not selected
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
border-top-left-radius: 0;
|
||||
border-bottom-left-radius: 0;
|
||||
border-left-width: 1px; // Ensure left border for the last button
|
||||
}
|
||||
|
||||
// Override Ant Design's default hover and focus styles for a cleaner look
|
||||
&:hover,
|
||||
&:focus {
|
||||
z-index: 1;
|
||||
border-color: ${(props) => (props.selected ? 'var(--ant-primary-color)' : 'var(--ant-primary-color-hover)')};
|
||||
box-shadow: ${(props) =>
|
||||
props.selected ? '0 0 0 2px var(--ant-primary-color-outline)' : '0 0 0 2px var(--ant-primary-color-outline)'};
|
||||
}
|
||||
`
|
||||
|
||||
const AssistantItem = styled.div`
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
height: 28px;
|
||||
`
|
||||
|
||||
const AssistantName = styled.span`
|
||||
max-width: calc(100% - 60px);
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
`
|
||||
|
||||
const Spacer = styled.div`
|
||||
flex: 1;
|
||||
`
|
||||
|
||||
const DefaultTag = styled.span<{ isCurrent: boolean }>`
|
||||
color: ${(props) => (props.isCurrent ? 'var(--color-primary)' : 'var(--color-text-3)')};
|
||||
font-size: 12px;
|
||||
padding: 2px 4px;
|
||||
border-radius: 4px;
|
||||
`
|
||||
|
||||
export default ModelSettings
|
||||
|
||||
@ -21,7 +21,7 @@ export interface LlmState {
|
||||
defaultModel: Model
|
||||
topicNamingModel: Model
|
||||
translateModel: Model
|
||||
quickAssistantModel: Model
|
||||
quickAssistantId: string | null
|
||||
settings: LlmSettings
|
||||
}
|
||||
|
||||
@ -514,7 +514,7 @@ const initialState: LlmState = {
|
||||
defaultModel: SYSTEM_MODELS.defaultModel[0],
|
||||
topicNamingModel: SYSTEM_MODELS.defaultModel[1],
|
||||
translateModel: SYSTEM_MODELS.defaultModel[2],
|
||||
quickAssistantModel: SYSTEM_MODELS.defaultModel[3],
|
||||
quickAssistantId: null,
|
||||
providers: INITIAL_PROVIDERS,
|
||||
settings: {
|
||||
ollama: {
|
||||
@ -621,8 +621,9 @@ const llmSlice = createSlice({
|
||||
setTranslateModel: (state, action: PayloadAction<{ model: Model }>) => {
|
||||
state.translateModel = action.payload.model
|
||||
},
|
||||
setQuickAssistantModel: (state, action: PayloadAction<{ model: Model }>) => {
|
||||
state.quickAssistantModel = action.payload.model
|
||||
|
||||
setQuickAssistantId: (state, action: PayloadAction<string | null>) => {
|
||||
state.quickAssistantId = action.payload
|
||||
},
|
||||
setOllamaKeepAliveTime: (state, action: PayloadAction<number>) => {
|
||||
state.settings.ollama.keepAliveTime = action.payload
|
||||
@ -661,7 +662,7 @@ export const {
|
||||
setDefaultModel,
|
||||
setTopicNamingModel,
|
||||
setTranslateModel,
|
||||
setQuickAssistantModel,
|
||||
setQuickAssistantId,
|
||||
setOllamaKeepAliveTime,
|
||||
setLMStudioKeepAliveTime,
|
||||
setGPUStackKeepAliveTime,
|
||||
|
||||
@ -1462,8 +1462,6 @@ const migrateConfig = {
|
||||
searchMessageShortcut.shortcut = [isMac ? 'Command' : 'Ctrl', 'Shift', 'F']
|
||||
}
|
||||
}
|
||||
// Quick assistant model
|
||||
state.llm.quickAssistantModel = state.llm.defaultModel || SYSTEM_MODELS.silicon[1]
|
||||
return state
|
||||
} catch (error) {
|
||||
return state
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import Scrollbar from '@renderer/components/Scrollbar'
|
||||
import { getDefaultModel } from '@renderer/services/AssistantService'
|
||||
import { Assistant } from '@renderer/types'
|
||||
import { FC } from 'react'
|
||||
import styled from 'styled-components'
|
||||
@ -11,11 +10,9 @@ interface Props {
|
||||
}
|
||||
|
||||
const ChatWindow: FC<Props> = ({ route, assistant }) => {
|
||||
// const { defaultAssistant } = useDefaultAssistant()
|
||||
|
||||
return (
|
||||
<Main className="bubble">
|
||||
<Messages assistant={{ ...assistant, model: getDefaultModel() }} route={route} />
|
||||
<Messages assistant={{ ...assistant }} route={route} />
|
||||
</Main>
|
||||
)
|
||||
}
|
||||
|
||||
@ -4,13 +4,13 @@ import { useDefaultAssistant, useDefaultModel } from '@renderer/hooks/useAssista
|
||||
import { useSettings } from '@renderer/hooks/useSettings'
|
||||
import i18n from '@renderer/i18n'
|
||||
import { fetchChatCompletion } from '@renderer/services/ApiService'
|
||||
import { getDefaultAssistant, getDefaultModel } from '@renderer/services/AssistantService'
|
||||
import { getAssistantById } from '@renderer/services/AssistantService'
|
||||
import { getAssistantMessage, getUserMessage } from '@renderer/services/MessagesService'
|
||||
import store from '@renderer/store'
|
||||
import store, { useAppSelector } from '@renderer/store'
|
||||
import { upsertManyBlocks } from '@renderer/store/messageBlock'
|
||||
import { updateOneBlock, upsertOneBlock } from '@renderer/store/messageBlock'
|
||||
import { newMessagesActions } from '@renderer/store/newMessage'
|
||||
import { ThemeMode } from '@renderer/types'
|
||||
import { Assistant, ThemeMode } from '@renderer/types'
|
||||
import { Chunk, ChunkType } from '@renderer/types/chunk'
|
||||
import { AssistantMessageStatus } from '@renderer/types/newMessage'
|
||||
import { MessageBlockStatus } from '@renderer/types/newMessage'
|
||||
@ -37,14 +37,14 @@ const HomeWindow: FC = () => {
|
||||
const [isFirstMessage, setIsFirstMessage] = useState(true)
|
||||
const [clipboardText, setClipboardText] = useState('')
|
||||
const [selectedText, setSelectedText] = useState('')
|
||||
const [currentAssistant, setCurrentAssistant] = useState<Assistant>({} as Assistant)
|
||||
const [text, setText] = useState('')
|
||||
const [lastClipboardText, setLastClipboardText] = useState<string | null>(null)
|
||||
const textChange = useState(() => {})[1]
|
||||
const { defaultAssistant } = useDefaultAssistant()
|
||||
const topic = defaultAssistant.topics[0]
|
||||
const { defaultModel, quickAssistantModel } = useDefaultModel()
|
||||
// 如果 quickAssistantModel 未設定,則使用 defaultModel
|
||||
const model = quickAssistantModel || defaultModel
|
||||
const { defaultModel } = useDefaultModel()
|
||||
const model = currentAssistant.model || defaultModel
|
||||
const { language, readClipboardAtStartup, windowStyle } = useSettings()
|
||||
const { theme } = useTheme()
|
||||
const { t } = useTranslation()
|
||||
@ -54,6 +54,8 @@ const HomeWindow: FC = () => {
|
||||
|
||||
const content = isFirstMessage ? (referenceText === text ? text : `${referenceText}\n\n${text}`).trim() : text.trim()
|
||||
|
||||
const { quickAssistantId } = useAppSelector((state) => state.llm)
|
||||
|
||||
const readClipboard = useCallback(async () => {
|
||||
if (!readClipboardAtStartup) return
|
||||
|
||||
@ -158,16 +160,36 @@ const HomeWindow: FC = () => {
|
||||
setText(e.target.value)
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
const defaultCurrentAssistant = {
|
||||
...defaultAssistant,
|
||||
model: defaultModel
|
||||
}
|
||||
|
||||
if (quickAssistantId) {
|
||||
// 獲取指定助手,如果不存在則使用默認助手
|
||||
const assistantFromId = getAssistantById(quickAssistantId)
|
||||
const currentAssistant = assistantFromId || defaultCurrentAssistant
|
||||
// 如果助手本身沒有設定模型,則使用預設模型
|
||||
if (!currentAssistant.model) {
|
||||
currentAssistant.model = defaultModel
|
||||
}
|
||||
setCurrentAssistant(currentAssistant)
|
||||
} else {
|
||||
setCurrentAssistant(defaultCurrentAssistant)
|
||||
}
|
||||
}, [quickAssistantId, defaultAssistant, defaultModel])
|
||||
|
||||
const onSendMessage = useCallback(
|
||||
async (prompt?: string) => {
|
||||
if (isEmpty(content)) {
|
||||
return
|
||||
}
|
||||
|
||||
const topic = currentAssistant.topics[0]
|
||||
const messageParams = {
|
||||
role: 'user',
|
||||
content: prompt ? `${prompt}\n\n${content}` : content,
|
||||
assistant: defaultAssistant,
|
||||
content: [prompt, content].filter(Boolean).join('\n\n'),
|
||||
assistant: currentAssistant,
|
||||
topic,
|
||||
createdAt: dayjs().format('YYYY-MM-DD HH:mm:ss'),
|
||||
status: 'success'
|
||||
@ -178,7 +200,7 @@ const HomeWindow: FC = () => {
|
||||
store.dispatch(newMessagesActions.addMessage({ topicId, message: userMessage }))
|
||||
store.dispatch(upsertManyBlocks(blocks))
|
||||
|
||||
const assistant = getDefaultAssistant()
|
||||
const assistant = currentAssistant
|
||||
let blockId: string | null = null
|
||||
let blockContent: string = ''
|
||||
|
||||
@ -187,7 +209,7 @@ const HomeWindow: FC = () => {
|
||||
|
||||
fetchChatCompletion({
|
||||
messages: [userMessage],
|
||||
assistant: { ...assistant, model: quickAssistantModel || getDefaultModel(), settings: { streamOutput: true } },
|
||||
assistant: { ...assistant, settings: { streamOutput: true } },
|
||||
onChunkReceived: (chunk: Chunk) => {
|
||||
if (chunk.type === ChunkType.TEXT_DELTA) {
|
||||
blockContent += chunk.text
|
||||
@ -224,7 +246,7 @@ const HomeWindow: FC = () => {
|
||||
setIsFirstMessage(false)
|
||||
setText('') // ✅ 清除输入框内容
|
||||
},
|
||||
[content, defaultAssistant, topic, quickAssistantModel]
|
||||
[content, currentAssistant, topic]
|
||||
)
|
||||
|
||||
const clearClipboard = () => {
|
||||
@ -277,7 +299,11 @@ const HomeWindow: FC = () => {
|
||||
text={text}
|
||||
model={model}
|
||||
referenceText={referenceText}
|
||||
placeholder={t('miniwindow.input.placeholder.empty', { model: model.name })}
|
||||
placeholder={
|
||||
quickAssistantId
|
||||
? t('miniwindow.input.placeholder.empty', { model: currentAssistant.name })
|
||||
: t('miniwindow.input.placeholder.empty', { model: model.name })
|
||||
}
|
||||
handleKeyDown={handleKeyDown}
|
||||
handleChange={handleChange}
|
||||
ref={inputBarRef}
|
||||
@ -290,7 +316,7 @@ const HomeWindow: FC = () => {
|
||||
<ClipboardPreview referenceText={referenceText} clearClipboard={clearClipboard} t={t} />
|
||||
</div>
|
||||
)}
|
||||
<ChatWindow route={route} assistant={defaultAssistant} />
|
||||
<ChatWindow route={route} assistant={currentAssistant ?? defaultAssistant} />
|
||||
<Divider style={{ margin: '10px 0' }} />
|
||||
<Footer route={route} onExit={() => setRoute('home')} />
|
||||
</Container>
|
||||
@ -316,7 +342,9 @@ const HomeWindow: FC = () => {
|
||||
placeholder={
|
||||
referenceText && route === 'home'
|
||||
? t('miniwindow.input.placeholder.title')
|
||||
: t('miniwindow.input.placeholder.empty', { model: model.name })
|
||||
: quickAssistantId
|
||||
? t('miniwindow.input.placeholder.empty', { model: currentAssistant.name })
|
||||
: t('miniwindow.input.placeholder.empty', { model: model.name })
|
||||
}
|
||||
handleKeyDown={handleKeyDown}
|
||||
handleChange={handleChange}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user