From a7b7ef087a0e3709f290c36e1bd04983fe70fa3c Mon Sep 17 00:00:00 2001 From: Arvin Xu Date: Tue, 21 Nov 2023 01:46:01 +0800 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20feat:=20support=20the=20auto=20crea?= =?UTF-8?q?te=20topic=20configuration=20(#490)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * ✨ feat: support the auto create topic configuration * 🐛 fix: fix the inbox session that not response on config * ♻️ refactor: rename the agentConfig folder to agent * 🎨 refactor: improve code * 🌐 chore: add i18n --- locales/en_US/setting.json | 10 +++- locales/ja_JP/setting.json | 10 +++- locales/ko_KR/setting.json | 10 +++- locales/ru_RU/setting.json | 10 +++- locales/zh_CN/setting.json | 8 +++ locales/zh_TW/setting.json | 10 +++- .../ChatHeader/ShareButton/Preview.tsx | 3 +- .../ChatInput/ActionBar/FileUpload.tsx | 2 +- .../ChatInput/ActionBar/ModelSwitch.tsx | 3 +- .../features/Conversation/usePluginsInit.ts | 2 +- .../features/SubmitAgentButton/Inner.tsx | 2 +- src/const/settings.ts | 2 + .../AgentSetting/AgentConfig/index.tsx | 18 +++++- src/hooks/useSTT.ts | 2 +- src/hooks/useTTS.ts | 2 +- src/locales/default/setting.ts | 8 +++ src/services/chat.ts | 6 +- .../__snapshots__/settings.test.ts.snap | 60 +++++++++++++++++++ src/store/global/selectors/settings.test.ts | 52 +--------------- src/store/global/slices/agent.ts | 6 +- src/store/session/initialState.ts | 1 - src/store/session/selectors.ts | 2 +- .../slices/{agentConfig => agent}/action.ts | 16 ++++- .../slices/{agentConfig => agent}/index.ts | 1 - .../{agentConfig => agent}/selectors.ts | 12 +++- .../slices/agentConfig/initialState.ts | 4 -- .../session/slices/chat/actions/message.ts | 8 ++- .../session/slices/chat/actions/share.ts | 2 +- .../session/slices/chat/selectors/chat.ts | 2 +- .../slices/chat/selectors/utils.test.ts | 4 ++ .../session/slices/session/initialState.ts | 17 ++---- .../slices/session/reducers/session.test.ts | 2 +- src/store/session/store.ts | 2 +- src/types/session.ts | 2 + 34 files changed, 201 insertions(+), 100 deletions(-) create mode 100644 src/store/global/selectors/__snapshots__/settings.test.ts.snap rename src/store/session/slices/{agentConfig => agent}/action.ts (68%) rename src/store/session/slices/{agentConfig => agent}/index.ts (63%) rename src/store/session/slices/{agentConfig => agent}/selectors.ts (88%) delete mode 100644 src/store/session/slices/agentConfig/initialState.ts diff --git a/locales/en_US/setting.json b/locales/en_US/setting.json index a0006a0b74a77..d94cafa482ddc 100644 --- a/locales/en_US/setting.json +++ b/locales/en_US/setting.json @@ -139,7 +139,15 @@ "placeholder": "{{text}} will be replaced with real-time input information", "title": "User Input Preprocessing" }, - "title": "Chat Settings" + "title": "Chat Settings", + "autoCreateTopicThreshold": { + "title": "Message Threshold", + "desc": "Automatically create a topic when the current message count exceeds this value" + }, + "enableAutoCreateTopic": { + "title": "Enable Auto Topic Creation", + "desc": "Whether to automatically create a topic during the conversation, only effective in temporary topics" + } }, "settingModel": { "enableMaxTokens": { diff --git a/locales/ja_JP/setting.json b/locales/ja_JP/setting.json index 23e77976088f9..0cfd116c3e053 100644 --- a/locales/ja_JP/setting.json +++ b/locales/ja_JP/setting.json @@ -139,7 +139,15 @@ "placeholder": "プリプロセステンプレート {{text}} はリアルタイムの入力情報に置き換えられます", "title": "ユーザー入力のプリプロセス" }, - "title": "チャット設定" + "title": "チャット設定", + "autoCreateTopicThreshold": { + "desc": "現在のメッセージ数がこの値を超えると、トピックが自動的に作成されます", + "title": "メッセージ閾値" + }, + "enableAutoCreateTopic": { + "desc": "会話中にトピックを自動的に作成するかどうか、一時的なトピックでのみ有効です", + "title": "トピックの自動作成" + } }, "settingModel": { "enableMaxTokens": { diff --git a/locales/ko_KR/setting.json b/locales/ko_KR/setting.json index 6e57e61e033c0..47bcd1c224cad 100644 --- a/locales/ko_KR/setting.json +++ b/locales/ko_KR/setting.json @@ -139,7 +139,15 @@ "placeholder": "사전 처리 템플릿 {{text}}은(는) 실시간 입력 정보로 대체됩니다.", "title": "사용자 입력 사전 처리" }, - "title": "채팅 설정" + "title": "채팅 설정", + "autoCreateTopicThreshold": { + "desc": "현재 메시지 수가이 값 이상이면 자동으로 주제를 만듭니다.", + "title": "메시지 임계값" + }, + "enableAutoCreateTopic": { + "desc": "대화 중에 주제를 자동으로 만들지 여부를 설정합니다. 임시 주제에서만 작동합니다.", + "title": "주제 자동 생성" + } }, "settingModel": { "enableMaxTokens": { diff --git a/locales/ru_RU/setting.json b/locales/ru_RU/setting.json index 66a714604b421..d13a1bf6575e6 100644 --- a/locales/ru_RU/setting.json +++ b/locales/ru_RU/setting.json @@ -139,7 +139,15 @@ "placeholder": "{{text}} будут заменены входной информацией, поступающей в режиме реального времени", "title": "Предварительная обработка пользовательского ввода" }, - "title": "Настройки чата" + "title": "Настройки чата", + "autoCreateTopicThreshold": { + "desc": "Когда текущее количество сообщений превысит эту величину, будет автоматически создана тема", + "title": "Порог сообщений" + }, + "enableAutoCreateTopic": { + "desc": "Автоматическое создание темы во время разговора, действует только во временной теме", + "title": "Включить автоматическое создание темы" + } }, "settingModel": { "enableMaxTokens": { diff --git a/locales/zh_CN/setting.json b/locales/zh_CN/setting.json index ffb4c62848e9e..2f0149cf060c8 100644 --- a/locales/zh_CN/setting.json +++ b/locales/zh_CN/setting.json @@ -110,6 +110,10 @@ "title": "助手信息" }, "settingChat": { + "autoCreateTopicThreshold": { + "desc": "当前消息数超过设定该值后,将自动创建话题", + "title": "消息阈值" + }, "chatStyleType": { "title": "聊天窗口样式", "type": { @@ -121,6 +125,10 @@ "desc": "当未压缩的历史消息超过该值时,将进行压缩", "title": "历史消息长度压缩阈值" }, + "enableAutoCreateTopic": { + "desc": "会话过程中是否自动创建话题,仅在临时话题中生效", + "title": "自动创建话题" + }, "enableCompressThreshold": { "title": "是否开启历史消息长度压缩阈值" }, diff --git a/locales/zh_TW/setting.json b/locales/zh_TW/setting.json index 8a35d00e054c3..8cc8e21fd2648 100644 --- a/locales/zh_TW/setting.json +++ b/locales/zh_TW/setting.json @@ -139,7 +139,15 @@ "placeholder": "前置處理範本 {{text}} 將替換為即時輸入資訊", "title": "使用者輸入前置處理" }, - "title": "聊天設定" + "title": "聊天設定", + "autoCreateTopicThreshold": { + "desc": "當前訊息數超過設定該值後,將自動創建話題", + "title": "訊息閾值" + }, + "enableAutoCreateTopic": { + "desc": "會話過程中是否自動創建話題,僅在臨時話題中生效", + "title": "自動創建話題" + } }, "settingModel": { "enableMaxTokens": { diff --git a/src/app/chat/features/ChatHeader/ShareButton/Preview.tsx b/src/app/chat/features/ChatHeader/ShareButton/Preview.tsx index ed2c4cb58c856..c87ac14aaa5bd 100644 --- a/src/app/chat/features/ChatHeader/ShareButton/Preview.tsx +++ b/src/app/chat/features/ChatHeader/ShareButton/Preview.tsx @@ -10,8 +10,7 @@ import ChatList from 'src/app/chat/features/Conversation/ChatList'; import pkg from '@/../package.json'; import { useSessionStore } from '@/store/session'; -import { agentSelectors } from '@/store/session/slices/agentConfig'; -import { sessionSelectors } from '@/store/session/slices/session/selectors'; +import { agentSelectors, sessionSelectors } from '@/store/session/selectors'; import PluginTag from '../../ChatHeader/PluginTag'; import { useStyles } from './style'; diff --git a/src/app/chat/features/ChatInput/ActionBar/FileUpload.tsx b/src/app/chat/features/ChatInput/ActionBar/FileUpload.tsx index f23d4bddecc84..256dfbecfcc5e 100644 --- a/src/app/chat/features/ChatInput/ActionBar/FileUpload.tsx +++ b/src/app/chat/features/ChatInput/ActionBar/FileUpload.tsx @@ -8,7 +8,7 @@ import { Center } from 'react-layout-kit'; import { useFileStore } from '@/store/files'; import { useSessionStore } from '@/store/session'; -import { agentSelectors } from '@/store/session/slices/agentConfig'; +import { agentSelectors } from '@/store/session/selectors'; const FileUpload = memo(() => { const { t } = useTranslation('chat'); diff --git a/src/app/chat/features/ChatInput/ActionBar/ModelSwitch.tsx b/src/app/chat/features/ChatInput/ActionBar/ModelSwitch.tsx index ed7343bcfa736..8dfc2675179aa 100644 --- a/src/app/chat/features/ChatInput/ActionBar/ModelSwitch.tsx +++ b/src/app/chat/features/ChatInput/ActionBar/ModelSwitch.tsx @@ -13,8 +13,7 @@ const ModelSwitch = memo(() => { const { t } = useTranslation('setting'); const [model, updateAgentConfig] = useSessionStore((s) => { - const config = agentSelectors.currentAgentConfig(s); - return [config.model, s.updateAgentConfig]; + return [agentSelectors.currentAgentModel(s), s.updateAgentConfig]; }); const modelList = useGlobalStore(settingsSelectors.modelList); diff --git a/src/app/chat/features/Conversation/usePluginsInit.ts b/src/app/chat/features/Conversation/usePluginsInit.ts index 046165a8b3564..a0a6921575f82 100644 --- a/src/app/chat/features/Conversation/usePluginsInit.ts +++ b/src/app/chat/features/Conversation/usePluginsInit.ts @@ -1,6 +1,6 @@ import { usePluginStore } from '@/store/plugin'; import { useSessionStore } from '@/store/session'; -import { agentSelectors } from '@/store/session/slices/agentConfig'; +import { agentSelectors } from '@/store/session/selectors'; export const usePluginsInit = () => { const [plugins] = useSessionStore((s) => [agentSelectors.currentAgentPlugins(s)]); diff --git a/src/app/chat/settings/features/SubmitAgentButton/Inner.tsx b/src/app/chat/settings/features/SubmitAgentButton/Inner.tsx index 5e0610ae63fe6..c3a1fee4a7b13 100644 --- a/src/app/chat/settings/features/SubmitAgentButton/Inner.tsx +++ b/src/app/chat/settings/features/SubmitAgentButton/Inner.tsx @@ -13,7 +13,7 @@ import { AGENTS_INDEX_GITHUB_ISSUE } from '@/const/url'; import AgentInfo from '@/features/AgentInfo'; import { useGlobalStore } from '@/store/global'; import { useSessionStore } from '@/store/session'; -import { agentSelectors } from '@/store/session/slices/agentConfig'; +import { agentSelectors } from '@/store/session/selectors'; const Inner = memo(() => { const { t } = useTranslation('setting'); diff --git a/src/const/settings.ts b/src/const/settings.ts index 1d14644b0319c..189faf19084a5 100644 --- a/src/const/settings.ts +++ b/src/const/settings.ts @@ -31,7 +31,9 @@ export const DEFAUTT_AGENT_TTS_CONFIG: LobeAgentTTSConfig = { export const VISION_MODEL_DEFAULT_MAX_TOKENS = 1000; export const DEFAULT_AGENT_CONFIG: LobeAgentConfig = { + autoCreateTopicThreshold: 2, displayMode: 'chat', + enableAutoCreateTopic: true, historyCount: 1, model: LanguageModel.GPT3_5, params: { diff --git a/src/features/AgentSetting/AgentConfig/index.tsx b/src/features/AgentSetting/AgentConfig/index.tsx index ff402c62023f8..22243c1a91704 100644 --- a/src/features/AgentSetting/AgentConfig/index.tsx +++ b/src/features/AgentSetting/AgentConfig/index.tsx @@ -55,11 +55,27 @@ const AgentConfig = memo(() => { minWidth: undefined, }, { - children: , + children: , desc: t('settingChat.inputTemplate.desc'), label: t('settingChat.inputTemplate.title'), name: 'inputTemplate', }, + { + children: , + desc: t('settingChat.enableAutoCreateTopic.desc'), + label: t('settingChat.enableAutoCreateTopic.title'), + minWidth: undefined, + name: 'enableAutoCreateTopic', + valuePropName: 'checked', + }, + { + children: , + desc: t('settingChat.autoCreateTopicThreshold.desc'), + divider: false, + hidden: !config.enableAutoCreateTopic, + label: t('settingChat.autoCreateTopicThreshold.title'), + name: 'autoCreateTopicThreshold', + }, { children: , label: t('settingChat.enableHistoryCount.title'), diff --git a/src/hooks/useSTT.ts b/src/hooks/useSTT.ts index 98a27dc8eecd0..763999ab863cb 100644 --- a/src/hooks/useSTT.ts +++ b/src/hooks/useSTT.ts @@ -12,7 +12,7 @@ import { createHeaderWithOpenAI } from '@/services/_header'; import { OPENAI_URLS } from '@/services/_url'; import { settingsSelectors, useGlobalStore } from '@/store/global'; import { useSessionStore } from '@/store/session'; -import { agentSelectors } from '@/store/session/slices/agentConfig'; +import { agentSelectors } from '@/store/session/selectors'; interface STTConfig extends SWRConfiguration { onTextChange: (value: string) => void; diff --git a/src/hooks/useTTS.ts b/src/hooks/useTTS.ts index a6e74887ee299..ce29698c6328d 100644 --- a/src/hooks/useTTS.ts +++ b/src/hooks/useTTS.ts @@ -14,7 +14,7 @@ import { createHeaderWithOpenAI } from '@/services/_header'; import { OPENAI_URLS, TTS_URL } from '@/services/_url'; import { settingsSelectors, useGlobalStore } from '@/store/global'; import { useSessionStore } from '@/store/session'; -import { agentSelectors } from '@/store/session/slices/agentConfig'; +import { agentSelectors } from '@/store/session/selectors'; import { TTSServer } from '@/types/session'; interface TTSConfig extends SWRConfiguration { diff --git a/src/locales/default/setting.ts b/src/locales/default/setting.ts index fca37441dbf29..8f7fcb9b82499 100644 --- a/src/locales/default/setting.ts +++ b/src/locales/default/setting.ts @@ -110,6 +110,10 @@ export default { title: '助手信息', }, settingChat: { + autoCreateTopicThreshold: { + desc: '当前消息数超过设定该值后,将自动创建话题', + title: '消息阈值', + }, chatStyleType: { title: '聊天窗口样式', type: { @@ -121,6 +125,10 @@ export default { desc: '当未压缩的历史消息超过该值时,将进行压缩', title: '历史消息长度压缩阈值', }, + enableAutoCreateTopic: { + desc: '会话过程中是否自动创建话题,仅在临时话题中生效', + title: '自动创建话题', + }, enableCompressThreshold: { title: '是否开启历史消息长度压缩阈值', }, diff --git a/src/services/chat.ts b/src/services/chat.ts index 10867855c81f6..0b9d067c90965 100644 --- a/src/services/chat.ts +++ b/src/services/chat.ts @@ -2,9 +2,9 @@ import { PluginRequestPayload, createHeadersWithPluginSettings } from '@lobehub/ import { merge } from 'lodash-es'; import { VISION_MODEL_WHITE_LIST } from '@/const/llm'; +import { DEFAULT_AGENT_CONFIG } from '@/const/settings'; import { usePluginStore } from '@/store/plugin'; import { pluginSelectors } from '@/store/plugin/selectors'; -import { initialLobeAgentConfig } from '@/store/session/initialState'; import type { OpenAIChatStreamPayload } from '@/types/openai/chat'; import { fetchAIFactory, getMessageError } from '@/utils/fetch'; @@ -22,9 +22,9 @@ class ChatService { ) => { const payload = merge( { - model: initialLobeAgentConfig.model, + model: DEFAULT_AGENT_CONFIG.model, stream: true, - ...initialLobeAgentConfig.params, + ...DEFAULT_AGENT_CONFIG.params, }, params, ); diff --git a/src/store/global/selectors/__snapshots__/settings.test.ts.snap b/src/store/global/selectors/__snapshots__/settings.test.ts.snap new file mode 100644 index 0000000000000..ea093468adc06 --- /dev/null +++ b/src/store/global/selectors/__snapshots__/settings.test.ts.snap @@ -0,0 +1,60 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`settingsSelectors > currentSettings > should merge DEFAULT_SETTINGS and s.settings correctly 1`] = ` +{ + "avatar": "avatar.jpg", + "defaultAgent": { + "config": { + "autoCreateTopicThreshold": 2, + "displayMode": "chat", + "enableAutoCreateTopic": true, + "historyCount": 1, + "model": "gpt-3.5-turbo", + "params": { + "frequency_penalty": 0, + "presence_penalty": 0, + "temperature": 0.6, + "top_p": 1, + }, + "plugins": [], + "systemRole": "", + "tts": { + "showAllLocaleVoice": false, + "sttLocale": "auto", + "ttsService": "openai", + "voice": { + "openai": "alloy", + }, + }, + }, + "meta": { + "avatar": "Default Agent", + "description": "Default agent for testing", + }, + }, + "fontSize": 14, + "language": "en-US", + "languageModel": { + "openAI": { + "OPENAI_API_KEY": "openai-api-key", + "customModelName": undefined, + "endpoint": "https://openai-endpoint.com", + "models": [ + "gpt-3.5-turbo", + ], + }, + }, + "neutralColor": "sand", + "password": "password123", + "primaryColor": "blue", + "themeMode": "light", + "tts": { + "openAI": { + "sttModel": "whisper-1", + "ttsModel": "tts-1", + }, + "sttAutoStop": true, + "sttServer": "openai", + }, +} +`; diff --git a/src/store/global/selectors/settings.test.ts b/src/store/global/selectors/settings.test.ts index 50bdb685de4c6..eda9214801283 100644 --- a/src/store/global/selectors/settings.test.ts +++ b/src/store/global/selectors/settings.test.ts @@ -54,57 +54,7 @@ describe('settingsSelectors', () => { const result = settingsSelectors.currentSettings(s); - expect(result).toEqual({ - avatar: 'avatar.jpg', - fontSize: 14, - language: 'en-US', - neutralColor: 'sand', - password: 'password123', - primaryColor: 'blue', - themeMode: 'light', - defaultAgent: { - config: { - displayMode: 'chat', - historyCount: 1, - systemRole: '', - model: LanguageModel.GPT3_5, - params: { - frequency_penalty: 0, - presence_penalty: 0, - temperature: 0.6, - top_p: 1, - }, - plugins: [], - tts: { - showAllLocaleVoice: false, - sttLocale: 'auto', - ttsService: 'openai', - voice: { - openai: 'alloy', - }, - }, - }, - meta: { - avatar: 'Default Agent', - description: 'Default agent for testing', - }, - }, - tts: { - openAI: { - sttModel: 'whisper-1', - ttsModel: 'tts-1', - }, - sttAutoStop: true, - sttServer: 'openai', - }, - languageModel: { - openAI: { - OPENAI_API_KEY: 'openai-api-key', - endpoint: 'https://openai-endpoint.com', - models: ['gpt-3.5-turbo'], - }, - }, - }); + expect(result).toMatchSnapshot(); }); }); diff --git a/src/store/global/slices/agent.ts b/src/store/global/slices/agent.ts index 6b5e92cbec610..a215774bbe3d9 100644 --- a/src/store/global/slices/agent.ts +++ b/src/store/global/slices/agent.ts @@ -1,8 +1,10 @@ import { produce } from 'immer'; +import { DeepPartial } from 'utility-types'; import type { StateCreator } from 'zustand/vanilla'; import { LobeAgentSettings } from '@/types/session'; import type { GlobalSettings } from '@/types/settings'; +import { merge } from '@/utils/merge'; import { setNamespace } from '@/utils/storeDebug'; import type { GlobalStore } from '../store'; @@ -13,7 +15,7 @@ const t = setNamespace('settings'); * 设置操作 */ export interface AgentAction { - updateDefaultAgent: (agent: Partial) => void; + updateDefaultAgent: (agent: DeepPartial) => void; } export const createAgentSlice: StateCreator< @@ -24,7 +26,7 @@ export const createAgentSlice: StateCreator< > = (set, get) => ({ updateDefaultAgent: (agent) => { const settings = produce(get().settings, (draft: GlobalSettings) => { - draft.defaultAgent = { ...draft.defaultAgent, ...agent }; + draft.defaultAgent = merge(draft.defaultAgent, agent); }); set({ settings }, false, t('updateDefaultAgent', agent)); diff --git a/src/store/session/initialState.ts b/src/store/session/initialState.ts index 6bbd22b108c08..b52d6310afcdc 100644 --- a/src/store/session/initialState.ts +++ b/src/store/session/initialState.ts @@ -8,5 +8,4 @@ export const initialState: SessionStoreState = { ...initialChatState, }; -export { initialLobeAgentConfig } from './slices/agentConfig'; export { initLobeSession } from './slices/session/initialState'; diff --git a/src/store/session/selectors.ts b/src/store/session/selectors.ts index e7adb38856681..68d5f44dde4e2 100644 --- a/src/store/session/selectors.ts +++ b/src/store/session/selectors.ts @@ -1,3 +1,3 @@ -export { agentSelectors } from './slices/agentConfig/selectors'; +export { agentSelectors } from './slices/agent/selectors'; export { chatSelectors, topicSelectors } from './slices/chat/selectors'; export { sessionSelectors } from './slices/session/selectors'; diff --git a/src/store/session/slices/agentConfig/action.ts b/src/store/session/slices/agent/action.ts similarity index 68% rename from src/store/session/slices/agentConfig/action.ts rename to src/store/session/slices/agent/action.ts index 762e946cea355..b0cd7e03d8df2 100644 --- a/src/store/session/slices/agentConfig/action.ts +++ b/src/store/session/slices/agent/action.ts @@ -1,6 +1,7 @@ import { produce } from 'immer'; import { StateCreator } from 'zustand/vanilla'; +import { useGlobalStore } from '@/store/global'; import { MetaData } from '@/types/meta'; import { LobeAgentConfig } from '@/types/session'; @@ -39,11 +40,22 @@ export const createAgentSlice: StateCreator< }, updateAgentConfig: (config) => { - const { activeId } = get(); + const { activeId, dispatchSession } = get(); const session = sessionSelectors.currentSession(get()); if (!activeId || !session) return; - get().dispatchSession({ config, id: activeId, type: 'updateSessionConfig' }); + // if is the inbox session, update the global config + if (sessionSelectors.isInboxSession(get())) { + useGlobalStore.getState().updateDefaultAgent({ config }); + // NOTE: DON'T ADD RETURN HERE. + // we need to use `dispatchSession` below to update inbox config to trigger the inbox config rerender + } + + // Although we use global store to store the default agent config, + // due to the `currentAgentConfig` selector use `useGlobalStore.getState()` + // to get the default agent config which not rerender on global store update + // we need to update the session config here. + dispatchSession({ config, id: activeId, type: 'updateSessionConfig' }); }, updateAgentMeta: (meta) => { diff --git a/src/store/session/slices/agentConfig/index.ts b/src/store/session/slices/agent/index.ts similarity index 63% rename from src/store/session/slices/agentConfig/index.ts rename to src/store/session/slices/agent/index.ts index 6bdd1f4b2ef1a..ffc794fb36877 100644 --- a/src/store/session/slices/agentConfig/index.ts +++ b/src/store/session/slices/agent/index.ts @@ -1,3 +1,2 @@ export * from './action'; -export * from './initialState'; export * from './selectors'; diff --git a/src/store/session/slices/agentConfig/selectors.ts b/src/store/session/slices/agent/selectors.ts similarity index 88% rename from src/store/session/slices/agentConfig/selectors.ts rename to src/store/session/slices/agent/selectors.ts index 20ef94a91d8fa..cfcd6822c6b56 100644 --- a/src/store/session/slices/agentConfig/selectors.ts +++ b/src/store/session/slices/agent/selectors.ts @@ -2,7 +2,8 @@ import { t } from 'i18next'; import { DEFAULT_OPENAI_MODEL_LIST, VISION_MODEL_WHITE_LIST } from '@/const/llm'; import { DEFAULT_AVATAR, DEFAULT_BACKGROUND_COLOR } from '@/const/meta'; -import { DEFAUTT_AGENT_TTS_CONFIG } from '@/const/settings'; +import { DEFAULT_AGENT_CONFIG, DEFAUTT_AGENT_TTS_CONFIG } from '@/const/settings'; +import { settingsSelectors, useGlobalStore } from '@/store/global'; import { SessionStore } from '@/store/session'; import { LanguageModel } from '@/types/llm'; import { MetaData } from '@/types/meta'; @@ -10,7 +11,6 @@ import { LobeAgentTTSConfig } from '@/types/session'; import { merge } from '@/utils/merge'; import { sessionSelectors } from '../session/selectors'; -import { initialLobeAgentConfig } from './initialState'; const currentAgentMeta = (s: SessionStore): MetaData => { const session = sessionSelectors.currentSession(s); @@ -22,7 +22,13 @@ const currentAgentTitle = (s: SessionStore) => currentAgentMeta(s)?.title || t(' const currentAgentConfig = (s: SessionStore) => { const session = sessionSelectors.currentSession(s); - return merge(initialLobeAgentConfig, session?.config); + + // if is the inbox session, use the default agent config in global store + if (sessionSelectors.isInboxSession(s)) { + return settingsSelectors.defaultAgentConfig(useGlobalStore.getState()); + } + + return merge(DEFAULT_AGENT_CONFIG, session?.config); }; const currentAgentSystemRole = (s: SessionStore) => { diff --git a/src/store/session/slices/agentConfig/initialState.ts b/src/store/session/slices/agentConfig/initialState.ts deleted file mode 100644 index 1c79a8c0490ab..0000000000000 --- a/src/store/session/slices/agentConfig/initialState.ts +++ /dev/null @@ -1,4 +0,0 @@ -import { DEFAULT_AGENT_CONFIG } from '@/const/settings'; -import { LobeAgentConfig } from '@/types/session'; - -export const initialLobeAgentConfig: LobeAgentConfig = DEFAULT_AGENT_CONFIG; diff --git a/src/store/session/slices/chat/actions/message.ts b/src/store/session/slices/chat/actions/message.ts index 9af237d1f7b9a..079abdb99710d 100644 --- a/src/store/session/slices/chat/actions/message.ts +++ b/src/store/session/slices/chat/actions/message.ts @@ -14,7 +14,7 @@ import { isFunctionMessageAtStart, testFunctionMessageAtEnd } from '@/utils/mess import { setNamespace } from '@/utils/storeDebug'; import { nanoid } from '@/utils/uuid'; -import { agentSelectors } from '../../agentConfig/selectors'; +import { agentSelectors } from '../../agent/selectors'; import { sessionSelectors } from '../../session/selectors'; import { FileDispatch, filesReducer } from '../reducers/files'; import { MessageDispatch, messagesReducer } from '../reducers/message'; @@ -388,7 +388,11 @@ export const chatMessage: StateCreator< // check activeTopic and then auto create topic const chats = chatSelectors.currentChats(get()); - if (!activeTopicId && chats.length >= 2) { + const agentConfig = agentSelectors.currentAgentConfig(get()); + // if autoCreateTopic is false, then stop + if (!agentConfig.enableAutoCreateTopic) return; + + if (!activeTopicId && chats.length >= agentConfig.autoCreateTopicThreshold) { const { saveToTopic, toggleTopic } = get(); const id = await saveToTopic(); if (id) toggleTopic(id); diff --git a/src/store/session/slices/chat/actions/share.ts b/src/store/session/slices/chat/actions/share.ts index 98bda8dc68136..6375b1273e3bd 100644 --- a/src/store/session/slices/chat/actions/share.ts +++ b/src/store/session/slices/chat/actions/share.ts @@ -7,7 +7,7 @@ import { genShareGPTUrl } from '@/services/shareGPT'; import { SessionStore } from '@/store/session'; import { ShareGPTConversation } from '@/types/share'; -import { agentSelectors } from '../../agentConfig'; +import { agentSelectors } from '../../agent'; import { sessionSelectors } from '../../session/selectors'; import { chatSelectors } from '../selectors'; diff --git a/src/store/session/slices/chat/selectors/chat.ts b/src/store/session/slices/chat/selectors/chat.ts index 726fbf6b00089..b21f830c432e7 100644 --- a/src/store/session/slices/chat/selectors/chat.ts +++ b/src/store/session/slices/chat/selectors/chat.ts @@ -7,7 +7,7 @@ import { useGlobalStore } from '@/store/global'; import { ChatMessage } from '@/types/chatMessage'; import type { SessionStore } from '../../../store'; -import { agentSelectors } from '../../agentConfig'; +import { agentSelectors } from '../../agent'; import { sessionSelectors } from '../../session/selectors'; import { getSlicedMessagesWithConfig } from '../utils'; import { currentTopics } from './topic'; diff --git a/src/store/session/slices/chat/selectors/utils.test.ts b/src/store/session/slices/chat/selectors/utils.test.ts index 7477d0feea6a2..e3225d0603a69 100644 --- a/src/store/session/slices/chat/selectors/utils.test.ts +++ b/src/store/session/slices/chat/selectors/utils.test.ts @@ -40,6 +40,8 @@ beforeEach(() => { params: { temperature: 0.6, }, + autoCreateTopicThreshold: 2, + enableAutoCreateTopic: true, systemRole: '', tts: { ttsService: 'openai', @@ -219,6 +221,8 @@ describe('organizeChats', () => { }, }, config: { + autoCreateTopicThreshold: 2, + enableAutoCreateTopic: true, model: 'gpt-4', params: { temperature: 0.6, diff --git a/src/store/session/slices/session/initialState.ts b/src/store/session/slices/session/initialState.ts index 3ce258140c706..3f8d80f62c1e5 100644 --- a/src/store/session/slices/session/initialState.ts +++ b/src/store/session/slices/session/initialState.ts @@ -1,10 +1,9 @@ -import { merge } from 'lodash-es'; import { AppRouterInstance } from 'next/dist/shared/lib/app-router-context.shared-runtime'; import { DEFAULT_AGENT_META, DEFAULT_INBOX_AVATAR } from '@/const/meta'; -import { LobeAgentConfig, LobeAgentSession, LobeSessionType } from '@/types/session'; - -import { initialLobeAgentConfig } from '../agentConfig/initialState'; +import { DEFAULT_AGENT_CONFIG } from '@/const/settings'; +import { LobeAgentSession, LobeSessionType } from '@/types/session'; +import { merge } from '@/utils/merge'; export interface SessionState { /** @@ -23,7 +22,7 @@ export interface SessionState { export const initLobeSession: LobeAgentSession = { chats: {}, - config: initialLobeAgentConfig, + config: DEFAULT_AGENT_CONFIG, createAt: Date.now(), files: [], id: '', @@ -31,16 +30,12 @@ export const initLobeSession: LobeAgentSession = { type: LobeSessionType.Agent, updateAt: Date.now(), }; - -export const initInbox = merge({}, initLobeSession, { - config: { - systemRole: '', - } as LobeAgentConfig, +export const initInbox: LobeAgentSession = merge(initLobeSession, { id: 'inbox', meta: { avatar: DEFAULT_INBOX_AVATAR, }, -} as Partial); +}); export const initialSessionState: SessionState = { activeId: 'inbox', diff --git a/src/store/session/slices/session/reducers/session.test.ts b/src/store/session/slices/session/reducers/session.test.ts index a0c5324e7913b..f7188711b1bc7 100644 --- a/src/store/session/slices/session/reducers/session.test.ts +++ b/src/store/session/slices/session/reducers/session.test.ts @@ -404,7 +404,7 @@ describe('sessionsReducer', () => { }, }, systemRole: 'system', - }; + } as LobeAgentConfig; }); const newState = sessionsReducer(state, payload); diff --git a/src/store/session/store.ts b/src/store/session/store.ts index 7e92527f705e4..4767ce13766ce 100644 --- a/src/store/session/store.ts +++ b/src/store/session/store.ts @@ -7,7 +7,7 @@ import { isDev } from '@/utils/env'; import { createHyperStorage } from '../middleware/createHyperStorage'; import { SessionStoreState, initialState } from './initialState'; -import { AgentAction, createAgentSlice } from './slices/agentConfig/action'; +import { AgentAction, createAgentSlice } from './slices/agent/action'; import { ChatAction, createChatSlice } from './slices/chat/actions'; import { SessionAction, createSessionSlice } from './slices/session/action'; diff --git a/src/types/session.ts b/src/types/session.ts index 3cc1ee2b935c6..008049a5151af 100644 --- a/src/types/session.ts +++ b/src/types/session.ts @@ -48,8 +48,10 @@ export interface LobeAgentTTSConfig { } export interface LobeAgentConfig { + autoCreateTopicThreshold: number; compressThreshold?: number; displayMode?: 'chat' | 'docs'; + enableAutoCreateTopic: boolean; /** * 历史消息长度压缩阈值 */