From 6cd1de521003d5a06f162318b79e321b91a1a183 Mon Sep 17 00:00:00 2001 From: arvinxx Date: Tue, 1 Aug 2023 22:52:51 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=F0=9F=92=84=20style:=20fix=20session=20ite?= =?UTF-8?q?m=20height?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/chat/SessionList/List/SessionItem.tsx | 3 +-- src/pages/chat/SessionList/List/style.ts | 1 - src/store/session/slices/chat/selectors/chat.ts | 17 +++++++++++++++++ .../session/slices/chat/selectors/index.ts | 3 ++- 4 files changed, 20 insertions(+), 4 deletions(-) diff --git a/src/pages/chat/SessionList/List/SessionItem.tsx b/src/pages/chat/SessionList/List/SessionItem.tsx index 6018359f8d01..30bd96412639 100644 --- a/src/pages/chat/SessionList/List/SessionItem.tsx +++ b/src/pages/chat/SessionList/List/SessionItem.tsx @@ -56,7 +56,7 @@ const SessionItem: FC = memo(({ id, active = true, loading }) meta.backgroundColor, session?.updateAt, session.config.model, - chatSelectors.currentChats(s).length, + chatSelectors.getChatsById(id)(s).length, s.removeSession, s.pinSession, ]; @@ -177,7 +177,6 @@ const SessionItem: FC = memo(({ id, active = true, loading }) pin={pin} ref={ref} showAction={open || isHovering} - style={{ color: theme.colorText }} title={title} /> ); diff --git a/src/pages/chat/SessionList/List/style.ts b/src/pages/chat/SessionList/List/style.ts index 8785bdb33c7a..758def1afb63 100644 --- a/src/pages/chat/SessionList/List/style.ts +++ b/src/pages/chat/SessionList/List/style.ts @@ -21,7 +21,6 @@ export const useStyles = createStyles(({ css, token }) => { `, container: css` position: relative; - height: 72px; `, modalRoot: css` diff --git a/src/store/session/slices/chat/selectors/chat.ts b/src/store/session/slices/chat/selectors/chat.ts index e2461bc8e7cc..c993e5017125 100644 --- a/src/store/session/slices/chat/selectors/chat.ts +++ b/src/store/session/slices/chat/selectors/chat.ts @@ -22,6 +22,23 @@ export const currentChats = (s: SessionStore): ChatMessage[] => { ); }; +export const getChatsById = + (id: string) => + (s: SessionStore): ChatMessage[] => { + const session = sessionSelectors.getSessionById(id)(s); + + if (!session) return []; + + return organizeChats( + session, + { + assistant: agentSelectors.currentAgentAvatar(s), + user: useSettings.getState().settings.avatar || DEFAULT_USER_AVATAR, + }, + s.activeTopicId, + ); + }; + export const systemRoleSel = (s: SessionStore): string => { const config = agentSelectors.currentAgentConfig(s); diff --git a/src/store/session/slices/chat/selectors/index.ts b/src/store/session/slices/chat/selectors/index.ts index 11e25921e885..0f83b4a12b56 100644 --- a/src/store/session/slices/chat/selectors/index.ts +++ b/src/store/session/slices/chat/selectors/index.ts @@ -1,10 +1,11 @@ -import { currentChats } from './chat'; +import { currentChats, getChatsById } from './chat'; import { chatsTokenCount, systemRoleTokenCount, totalTokenCount } from './token'; import { currentTopics, getTopicMessages } from './topic'; export const chatSelectors = { chatsTokenCount, currentChats, + getChatsById, systemRoleTokenCount, totalTokenCount, }; From 7baa02283f8971a0f320f845bcde3598a7a97616 Mon Sep 17 00:00:00 2001 From: arvinxx Date: Tue, 1 Aug 2023 23:43:36 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E2=9C=A8=20feat:=20=E5=AE=9E=E7=8E=B0?= =?UTF-8?q?=E8=87=AA=E5=AE=9A=E4=B9=89=E5=8E=86=E5=8F=B2=E6=B6=88=E6=81=AF?= =?UTF-8?q?=E6=95=B0=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/SliderWithInput/index.tsx | 3 + src/locales/default/setting.ts | 5 +- .../chat/[id]/Conversation/Input/Action.tsx | 80 +++++++++++-------- .../[id]/Conversation/Input/ActionRight.tsx | 31 +++++++ .../chat/[id]/Conversation/Input/index.tsx | 2 + .../session/slices/chat/actions/message.ts | 21 ++--- .../session/slices/chat/selectors/chat.ts | 30 +++---- .../session/slices/chat/selectors/token.ts | 12 ++- src/store/session/slices/chat/utils.ts | 13 +++ 9 files changed, 133 insertions(+), 64 deletions(-) create mode 100644 src/pages/chat/[id]/Conversation/Input/ActionRight.tsx create mode 100644 src/store/session/slices/chat/utils.ts diff --git a/src/components/SliderWithInput/index.tsx b/src/components/SliderWithInput/index.tsx index 93bfd968624f..4269b617f67b 100644 --- a/src/components/SliderWithInput/index.tsx +++ b/src/components/SliderWithInput/index.tsx @@ -21,6 +21,7 @@ const SliderWithInput = memo( controls, style, className, + disabled, ...props }) => { const handleOnchange = useCallback((value: number | null) => { @@ -38,6 +39,7 @@ const SliderWithInput = memo( > ( { const { t } = useTranslation('setting'); - const [clearMessage, updateAgentConfig] = useSessionStore( - (s) => [s.clearMessage, s.updateAgentConfig], - shallow, - ); - const [model, temperature] = useSessionStore((s) => { + + const [model, temperature, historyCount, unlimited, updateAgentConfig] = useSessionStore((s) => { const config = agentSelectors.currentAgentConfig(s); return [ config.model, config.params.temperature, - // config.historyCount + config.historyCount, + !config.enableHistoryCount, + s.updateAgentConfig, ]; }, shallow); @@ -54,6 +54,7 @@ const InputActions = memo(() => { value={temperature} /> } + placement={'top'} trigger={'click'} > { title={t('settingModel.temperature.titleWithValue', { value: temperature })} /> - {/*TODO 历史记录功能实现 */} - {/* {*/} - {/* updateAgentConfig({ historyCount: v });*/} - {/* }}*/} - {/* step={1}*/} - {/* style={{ width: 120 }}*/} - {/* value={historyCount}*/} - {/* />*/} - {/* }*/} - {/* trigger={'click'}*/} - {/*>*/} - {/* */} - {/**/} - clearMessage()} - title={t('confirmClearCurrentMessages', { ns: 'common' })} + + { + updateAgentConfig({ historyCount: v }); + }} + step={1} + style={{ width: 160 }} + value={historyCount} + /> + + { + updateAgentConfig({ enableHistoryCount: !checked }); + }} + size={'small'} + /> + {t('settingChat.enableHistoryCount.alias')} + + + } + placement={'top'} + trigger={'click'} > - + ); }); diff --git a/src/pages/chat/[id]/Conversation/Input/ActionRight.tsx b/src/pages/chat/[id]/Conversation/Input/ActionRight.tsx new file mode 100644 index 000000000000..51c8187f7654 --- /dev/null +++ b/src/pages/chat/[id]/Conversation/Input/ActionRight.tsx @@ -0,0 +1,31 @@ +import { ActionIcon } from '@lobehub/ui'; +import { Popconfirm } from 'antd'; +import { Eraser } from 'lucide-react'; +import { memo } from 'react'; +import { useTranslation } from 'react-i18next'; +import { shallow } from 'zustand/shallow'; + +import { useSessionStore } from '@/store/session'; + +const ActionsRight = memo(() => { + const { t } = useTranslation('setting'); + const [clearMessage] = useSessionStore((s) => [s.clearMessage, s.updateAgentConfig], shallow); + + return ( + clearMessage()} + title={t('confirmClearCurrentMessages', { ns: 'common' })} + > + + + ); +}); + +export default ActionsRight; diff --git a/src/pages/chat/[id]/Conversation/Input/index.tsx b/src/pages/chat/[id]/Conversation/Input/index.tsx index ab2e94fa11d2..03f8a31e667d 100644 --- a/src/pages/chat/[id]/Conversation/Input/index.tsx +++ b/src/pages/chat/[id]/Conversation/Input/index.tsx @@ -10,6 +10,7 @@ import { useSessionStore } from '@/store/session'; import { useSettings } from '@/store/settings'; import InputActions from './Action'; +import ActionsRight from './ActionRight'; import Token from './Token'; const ChatInput = () => { @@ -52,6 +53,7 @@ const ChatInput = () => { } + actionsRight={} expand={expand} footer={footer} minHeight={CHAT_TEXTAREA_HEIGHT} diff --git a/src/store/session/slices/chat/actions/message.ts b/src/store/session/slices/chat/actions/message.ts index bb7bf4b2e5bd..46f1eb9f2255 100644 --- a/src/store/session/slices/chat/actions/message.ts +++ b/src/store/session/slices/chat/actions/message.ts @@ -5,6 +5,7 @@ import { LOADING_FLAT } from '@/const/message'; import { fetchChatModel } from '@/services/chatModel'; import { fetchPlugin } from '@/services/plugin'; import { SessionStore, agentSelectors, chatSelectors, sessionSelectors } from '@/store/session'; +import { getSlicedMessagesWithConfig } from '@/store/session/slices/chat/utils'; import { ChatMessage, OpenAIFunctionCall } from '@/types/chatMessage'; import { fetchSSE } from '@/utils/fetch'; import { isFunctionMessage } from '@/utils/message'; @@ -123,12 +124,17 @@ export const chatMessage: StateCreator< const compiler = template(config.inputTemplate, { interpolate: /{{([\S\s]+?)}}/g }); - // 对 message 做统一预处理 + // ========================== // + // 对 messages 做统一预处理 // + // ========================== // - // 1. 替换 inputMessage 模板 + // 1. 按参数设定截断长度 + const slicedMessages = getSlicedMessagesWithConfig(messages, config); + + // 2. 替换 inputMessage 模板 const postMessages = !config.inputTemplate - ? messages - : messages.map((m) => { + ? slicedMessages + : slicedMessages.map((m) => { if (m.role === 'user') { try { return { ...m, content: compiler({ text: m.content }) }; @@ -141,12 +147,9 @@ export const chatMessage: StateCreator< return m; }); - // 2. TODO 按参数设定截断长度 - // 3. 添加 systemRole - const { systemRole } = agentSelectors.currentAgentConfig(get()); - if (systemRole) { - postMessages.unshift({ content: systemRole, role: 'system' } as ChatMessage); + if (config.systemRole) { + postMessages.unshift({ content: config.systemRole, role: 'system' } as ChatMessage); } const fetcher = () => diff --git a/src/store/session/slices/chat/selectors/chat.ts b/src/store/session/slices/chat/selectors/chat.ts index c993e5017125..7ee69a3d7672 100644 --- a/src/store/session/slices/chat/selectors/chat.ts +++ b/src/store/session/slices/chat/selectors/chat.ts @@ -1,27 +1,13 @@ import { DEFAULT_USER_AVATAR } from '@/const/meta'; -import { agentSelectors } from '@/store/session'; import { useSettings } from '@/store/settings'; import { ChatMessage } from '@/types/chatMessage'; import type { SessionStore } from '../../../store'; +import { agentSelectors } from '../../agentConfig'; import { sessionSelectors } from '../../session'; +import { getSlicedMessagesWithConfig } from '../utils'; import { organizeChats } from './utils'; -// 展示在聊天框中的消息 -export const currentChats = (s: SessionStore): ChatMessage[] => { - const session = sessionSelectors.currentSession(s); - if (!session) return []; - - return organizeChats( - session, - { - assistant: agentSelectors.currentAgentAvatar(s), - user: useSettings.getState().settings.avatar || DEFAULT_USER_AVATAR, - }, - s.activeTopicId, - ); -}; - export const getChatsById = (id: string) => (s: SessionStore): ChatMessage[] => { @@ -39,8 +25,16 @@ export const getChatsById = ); }; -export const systemRoleSel = (s: SessionStore): string => { +// 当前激活的消息列表 +export const currentChats = (s: SessionStore): ChatMessage[] => { + if (!s.activeId) return []; + + return getChatsById(s.activeId)(s); +}; + +export const currentChatsWithHistoryConfig = (s: SessionStore): ChatMessage[] => { + const chats = currentChats(s); const config = agentSelectors.currentAgentConfig(s); - return config.systemRole; + return getSlicedMessagesWithConfig(chats, config); }; diff --git a/src/store/session/slices/chat/selectors/token.ts b/src/store/session/slices/chat/selectors/token.ts index 7e81af03c514..af4b276e436d 100644 --- a/src/store/session/slices/chat/selectors/token.ts +++ b/src/store/session/slices/chat/selectors/token.ts @@ -1,7 +1,15 @@ import { encode } from 'gpt-tokenizer'; +import { agentSelectors } from '@/store/session'; + import type { SessionStore } from '../../../store'; -import { currentChats, systemRoleSel } from './chat'; +import { currentChatsWithHistoryConfig } from './chat'; + +export const systemRoleSel = (s: SessionStore): string => { + const config = agentSelectors.currentAgentConfig(s); + + return config.systemRole; +}; const systemRoleTokens = (s: SessionStore): number[] => { const systemRole = systemRoleSel(s); @@ -10,7 +18,7 @@ const systemRoleTokens = (s: SessionStore): number[] => { }; const chatsTokens = (s: SessionStore): number[] => { - const chats = currentChats(s); + const chats = currentChatsWithHistoryConfig(s); return encode(chats.map((m) => m.content).join('')); }; diff --git a/src/store/session/slices/chat/utils.ts b/src/store/session/slices/chat/utils.ts new file mode 100644 index 000000000000..c37367d1a931 --- /dev/null +++ b/src/store/session/slices/chat/utils.ts @@ -0,0 +1,13 @@ +import { ChatMessage } from '@/types/chatMessage'; +import { LobeAgentConfig } from '@/types/session'; + +export const getSlicedMessagesWithConfig = ( + messages: ChatMessage[], + config: LobeAgentConfig, +): ChatMessage[] => { + // 如果没有开启历史消息数限制,或者限制为 0,则直接返回 + if (!config.enableHistoryCount || !config.historyCount) return messages; + + // 如果开启了,则返回尾部的N条消息 + return messages.reverse().slice(0, config.historyCount).reverse(); +};