diff --git a/web/src/assets/svg/assistant.svg b/web/src/assets/svg/assistant.svg
new file mode 100644
index 000000000..43446a186
--- /dev/null
+++ b/web/src/assets/svg/assistant.svg
@@ -0,0 +1,25 @@
+
\ No newline at end of file
diff --git a/web/src/pages/chat/chat-container/index.less b/web/src/pages/chat/chat-container/index.less
index ff6eec79c..7b9a25493 100644
--- a/web/src/pages/chat/chat-container/index.less
+++ b/web/src/pages/chat/chat-container/index.less
@@ -1,11 +1,14 @@
.chatContainer {
padding: 0 24px 24px;
+ .messageContainer {
+ overflow-y: auto;
+ }
}
.messageItem {
.messageItemContent {
display: inline-block;
- width: 300px;
+ width: 400px;
}
}
diff --git a/web/src/pages/chat/chat-container/index.tsx b/web/src/pages/chat/chat-container/index.tsx
index b58b52f65..265509e61 100644
--- a/web/src/pages/chat/chat-container/index.tsx
+++ b/web/src/pages/chat/chat-container/index.tsx
@@ -1,4 +1,4 @@
-import { Button, Flex, Input, Typography } from 'antd';
+import { Button, Flex, Input } from 'antd';
import { ChangeEventHandler, useState } from 'react';
import { Message } from '@/interfaces/database/chat';
@@ -9,8 +9,6 @@ import { MessageType } from '@/constants/chat';
import { IClientConversation } from '../interface';
import styles from './index.less';
-const { Paragraph } = Typography;
-
const MessageItem = ({ item }: { item: Message }) => {
return (
{
})}
>
-
- {item.content}
-
+ {item.content}
);
@@ -44,10 +40,12 @@ const ChatContainer = () => {
return (
-
- {conversation?.message?.map((message) => (
-
- ))}
+
+
+ {conversation?.message?.map((message) => (
+
+ ))}
+
{
const dispatch = useDispatch();
@@ -137,24 +139,6 @@ export const useRemoveDialog = () => {
return { onRemoveDialog };
};
-export const useClickDialogCard = () => {
- const [currentQueryParameters, setSearchParams] = useSearchParams();
-
- const newQueryParameters: URLSearchParams = useMemo(() => {
- return new URLSearchParams(currentQueryParameters.toString());
- }, [currentQueryParameters]);
-
- const handleClickDialog = useCallback(
- (dialogId: string) => {
- newQueryParameters.set(ChatSearchParams.DialogId, dialogId);
- setSearchParams(newQueryParameters);
- },
- [newQueryParameters, setSearchParams],
- );
-
- return { handleClickDialog };
-};
-
export const useGetChatSearchParams = () => {
const [currentQueryParameters] = useSearchParams();
@@ -165,6 +149,44 @@ export const useGetChatSearchParams = () => {
};
};
+export const useSetCurrentConversation = () => {
+ const dispatch = useDispatch();
+
+ const setCurrentConversation = useCallback(
+ (currentConversation: IClientConversation) => {
+ dispatch({
+ type: 'chatModel/setCurrentConversation',
+ payload: currentConversation,
+ });
+ },
+ [dispatch],
+ );
+
+ return setCurrentConversation;
+};
+
+export const useClickDialogCard = () => {
+ const [currentQueryParameters, setSearchParams] = useSearchParams();
+
+ const newQueryParameters: URLSearchParams = useMemo(() => {
+ return new URLSearchParams();
+ }, []);
+
+ const handleClickDialog = useCallback(
+ (dialogId: string) => {
+ newQueryParameters.set(ChatSearchParams.DialogId, dialogId);
+ // newQueryParameters.set(
+ // ChatSearchParams.ConversationId,
+ // EmptyConversationId,
+ // );
+ setSearchParams(newQueryParameters);
+ },
+ [newQueryParameters, setSearchParams],
+ );
+
+ return { handleClickDialog };
+};
+
export const useSelectFirstDialogOnMount = () => {
const dialogList = useFetchDialogList();
const { dialogId } = useGetChatSearchParams();
@@ -182,13 +204,83 @@ export const useSelectFirstDialogOnMount = () => {
//#region conversation
-export const useFetchConversationList = (dialogId?: string) => {
+export const useCreateTemporaryConversation = () => {
+ const dispatch = useDispatch();
+ const { dialogId } = useGetChatSearchParams();
+ const { handleClickConversation } = useClickConversationCard();
+ let chatModel = useSelector((state: any) => state.chatModel);
+
+ const currentConversation: Pick<
+ IClientConversation,
+ 'id' | 'message' | 'name' | 'dialog_id'
+ > = chatModel.currentConversation;
+
+ const conversationList: IClientConversation[] = chatModel.conversationList;
+ const currentDialog: IDialog = chatModel.currentDialog;
+
+ const setCurrentConversation = useSetCurrentConversation();
+
+ const createTemporaryConversation = useCallback(() => {
+ const firstConversation = conversationList[0];
+ const messages = [...(firstConversation?.message ?? [])];
+ if (messages.some((x) => x.id === EmptyConversationId)) {
+ return;
+ }
+ messages.push({
+ id: EmptyConversationId,
+ content: currentDialog?.prompt_config?.prologue ?? '',
+ role: MessageType.Assistant,
+ });
+
+ let nextCurrentConversation = currentConversation;
+
+ // It’s the back-end data.
+ if ('id' in currentConversation) {
+ nextCurrentConversation = { ...currentConversation, message: messages };
+ } else {
+ // client data
+ nextCurrentConversation = {
+ id: EmptyConversationId,
+ name: 'New conversation',
+ dialog_id: dialogId,
+ message: messages,
+ };
+ }
+
+ const nextConversationList = [...conversationList];
+
+ nextConversationList.unshift(
+ nextCurrentConversation as IClientConversation,
+ );
+
+ setCurrentConversation(nextCurrentConversation as IClientConversation);
+
+ dispatch({
+ type: 'chatModel/setConversationList',
+ payload: nextConversationList,
+ });
+ handleClickConversation(EmptyConversationId);
+ }, [
+ dispatch,
+ currentConversation,
+ dialogId,
+ setCurrentConversation,
+ handleClickConversation,
+ conversationList,
+ currentDialog,
+ ]);
+
+ return { createTemporaryConversation };
+};
+
+export const useFetchConversationList = () => {
const dispatch = useDispatch();
const conversationList: any[] = useSelector(
(state: any) => state.chatModel.conversationList,
);
+ const { dialogId } = useGetChatSearchParams();
- const fetchConversationList = useCallback(() => {
+ const fetchConversationList = useCallback(async () => {
if (dialogId) {
dispatch({
type: 'chatModel/listConversation',
@@ -204,72 +296,56 @@ export const useFetchConversationList = (dialogId?: string) => {
return conversationList;
};
-export const useClickConversationCard = () => {
- const [currentQueryParameters, setSearchParams] = useSearchParams();
- const newQueryParameters: URLSearchParams = new URLSearchParams(
- currentQueryParameters.toString(),
- );
+export const useSelectConversationList = () => {
+ const [list, setList] = useState>([]);
+ let chatModel: ChatModelState = useSelector((state: any) => state.chatModel);
+ const { conversationList, currentDialog } = chatModel;
+ const { dialogId } = useGetChatSearchParams();
+ const prologue = currentDialog?.prompt_config?.prologue ?? '';
- const handleClickConversation = (conversationId: string) => {
- newQueryParameters.set(ChatSearchParams.ConversationId, conversationId);
- setSearchParams(newQueryParameters);
- };
+ const addTemporaryConversation = useCallback(() => {
+ setList(() => {
+ const nextList = [
+ {
+ id: '',
+ name: 'New conversation',
+ dialog_id: dialogId,
+ message: [
+ {
+ content: prologue,
+ role: MessageType.Assistant,
+ },
+ ],
+ } as IConversation,
+ ...conversationList,
+ ];
+ return nextList;
+ });
+ }, [conversationList, dialogId, prologue]);
- return { handleClickConversation };
+ useEffect(() => {
+ addTemporaryConversation();
+ }, [addTemporaryConversation]);
+
+ return { list, addTemporaryConversation };
};
-export const useCreateTemporaryConversation = () => {
- const dispatch = useDispatch();
- const { dialogId } = useGetChatSearchParams();
- const { handleClickConversation } = useClickConversationCard();
- let chatModel = useSelector((state: any) => state.chatModel);
- let currentConversation: Pick<
- IClientConversation,
- 'id' | 'message' | 'name' | 'dialog_id'
- > = chatModel.currentConversation;
- let conversationList: IClientConversation[] = chatModel.conversationList;
+export const useClickConversationCard = () => {
+ const [currentQueryParameters, setSearchParams] = useSearchParams();
+ const newQueryParameters: URLSearchParams = useMemo(
+ () => new URLSearchParams(currentQueryParameters.toString()),
+ [currentQueryParameters],
+ );
- const createTemporaryConversation = (message: string) => {
- const messages = [...(currentConversation?.message ?? [])];
- if (messages.some((x) => x.id === EmptyConversationId)) {
- return;
- }
- messages.unshift({
- id: EmptyConversationId,
- content: message,
- role: MessageType.Assistant,
- });
+ const handleClickConversation = useCallback(
+ (conversationId: string) => {
+ newQueryParameters.set(ChatSearchParams.ConversationId, conversationId);
+ setSearchParams(newQueryParameters);
+ },
+ [newQueryParameters, setSearchParams],
+ );
- // It’s the back-end data.
- if ('id' in currentConversation) {
- currentConversation = { ...currentConversation, message: messages };
- } else {
- // client data
- currentConversation = {
- id: EmptyConversationId,
- name: 'New conversation',
- dialog_id: dialogId,
- message: messages,
- };
- }
-
- const nextConversationList = [...conversationList];
-
- nextConversationList.push(currentConversation as IClientConversation);
-
- dispatch({
- type: 'chatModel/setCurrentConversation',
- payload: currentConversation,
- });
-
- dispatch({
- type: 'chatModel/setConversationList',
- payload: nextConversationList,
- });
- handleClickConversation(EmptyConversationId);
- };
-
- return { createTemporaryConversation };
+ return { handleClickConversation };
};
export const useSetConversation = () => {
@@ -302,17 +378,20 @@ export const useFetchConversation = () => {
const conversation = useSelector(
(state: any) => state.chatModel.currentConversation,
);
+ const setCurrentConversation = useSetCurrentConversation();
const fetchConversation = useCallback(() => {
- if (conversationId !== EmptyConversationId && conversationId !== '') {
- dispatch({
+ if (isConversationIdNotExist(conversationId)) {
+ dispatch({
type: 'chatModel/getConversation',
payload: {
conversation_id: conversationId,
},
});
+ } else {
+ setCurrentConversation({} as IClientConversation);
}
- }, [dispatch, conversationId]);
+ }, [dispatch, conversationId, setCurrentConversation]);
useEffect(() => {
fetchConversation();
diff --git a/web/src/pages/chat/index.tsx b/web/src/pages/chat/index.tsx
index 33b20e44c..4e3124f32 100644
--- a/web/src/pages/chat/index.tsx
+++ b/web/src/pages/chat/index.tsx
@@ -18,11 +18,11 @@ import ChatContainer from './chat-container';
import {
useClickConversationCard,
useClickDialogCard,
- useCreateTemporaryConversation,
useFetchConversationList,
useFetchDialog,
useGetChatSearchParams,
useRemoveDialog,
+ useSelectConversationList,
useSelectFirstDialogOnMount,
useSetCurrentDialog,
} from './hooks';
@@ -38,12 +38,10 @@ const Chat = () => {
const { handleClickDialog } = useClickDialogCard();
const { handleClickConversation } = useClickConversationCard();
const { dialogId, conversationId } = useGetChatSearchParams();
- const list = useFetchConversationList(dialogId);
- const { createTemporaryConversation } = useCreateTemporaryConversation();
+ const { list: conversationList, addTemporaryConversation } =
+ useSelectConversationList();
- const selectedDialog = useFetchDialog(dialogId, true);
-
- const prologue = selectedDialog?.prompt_config?.prologue || '';
+ useFetchDialog(dialogId, true);
const handleAppCardEnter = (id: string) => () => {
setActivated(id);
@@ -69,8 +67,8 @@ const Chat = () => {
};
const handleCreateTemporaryConversation = useCallback(() => {
- createTemporaryConversation(prologue);
- }, [createTemporaryConversation, prologue]);
+ addTemporaryConversation();
+ }, [addTemporaryConversation]);
const items: MenuProps['items'] = [
{
@@ -112,6 +110,8 @@ const Chat = () => {
return appItems;
};
+ useFetchConversationList();
+
return (
@@ -171,7 +171,7 @@ const Chat = () => {
- {list.map((x) => (
+ {conversationList.map((x) => (
= {
};
},
setCurrentConversation(state, { payload }) {
- const messageList = payload?.message.map((x: Message | IMessage) => ({
- ...x,
- id: 'id' in x ? x.id : uuid(),
- }));
+ const messageList =
+ payload?.message?.map((x: Message | IMessage) => ({
+ ...x,
+ id: 'id' in x ? x.id : uuid(),
+ })) ?? [];
return {
...state,
currentConversation: { ...payload, message: messageList },
diff --git a/web/src/pages/chat/utils.ts b/web/src/pages/chat/utils.ts
index 997dc3755..cbec9e2c7 100644
--- a/web/src/pages/chat/utils.ts
+++ b/web/src/pages/chat/utils.ts
@@ -1,4 +1,4 @@
-import { variableEnabledFieldMap } from './constants';
+import { EmptyConversationId, variableEnabledFieldMap } from './constants';
export const excludeUnEnabledVariables = (values: any) => {
const unEnabledFields: Array =
@@ -10,3 +10,7 @@ export const excludeUnEnabledVariables = (values: any) => {
(key) => `llm_setting.${variableEnabledFieldMap[key]}`,
);
};
+
+export const isConversationIdNotExist = (conversationId: string) => {
+ return conversationId !== EmptyConversationId && conversationId !== '';
+};