feat: Support for conversational streaming (#809)

### What problem does this PR solve?

feat: Support for conversational streaming
#709

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
This commit is contained in:
balibabu
2024-05-16 20:15:02 +08:00
committed by GitHub
parent 95f809187e
commit c6c9dbde64
21 changed files with 424 additions and 255 deletions

View File

@ -1,7 +1,6 @@
import { MessageType } from '@/constants/chat';
import { fileIconMap } from '@/constants/common';
import {
useCompleteConversation,
useCreateToken,
useFetchConversation,
useFetchConversationList,
@ -24,8 +23,14 @@ import {
useShowDeleteConfirm,
useTranslate,
} from '@/hooks/commonHooks';
import { useSendMessageWithSse } from '@/hooks/logicHooks';
import { useOneNamespaceEffectsLoading } from '@/hooks/storeHooks';
import { IConversation, IDialog, IStats } from '@/interfaces/database/chat';
import {
IAnswer,
IConversation,
IDialog,
IStats,
} from '@/interfaces/database/chat';
import { IChunk } from '@/interfaces/database/knowledge';
import { getFileExtension } from '@/utils';
import { message } from 'antd';
@ -380,31 +385,56 @@ export const useSelectCurrentConversation = () => {
const dialog = useSelectCurrentDialog();
const { conversationId, dialogId } = useGetChatSearchParams();
const addNewestConversation = useCallback((message: string) => {
const addNewestConversation = useCallback(
(message: string, answer: string = '') => {
setCurrentConversation((pre) => {
return {
...pre,
message: [
...pre.message,
{
role: MessageType.User,
content: message,
id: uuid(),
} as IMessage,
{
role: MessageType.Assistant,
content: answer,
id: uuid(),
reference: [],
} as IMessage,
],
};
});
},
[],
);
const addNewestAnswer = useCallback((answer: IAnswer) => {
setCurrentConversation((pre) => {
return {
...pre,
message: [
...pre.message,
{
role: MessageType.User,
content: message,
id: uuid(),
} as IMessage,
{
role: MessageType.Assistant,
content: '',
id: uuid(),
reference: [],
} as IMessage,
],
};
const latestMessage = pre.message?.at(-1);
if (latestMessage) {
return {
...pre,
message: [
...pre.message.slice(0, -1),
{
...latestMessage,
content: answer.answer,
reference: answer.reference,
} as IMessage,
],
};
}
return pre;
});
}, []);
const removeLatestMessage = useCallback(() => {
console.info('removeLatestMessage');
setCurrentConversation((pre) => {
const nextMessages = pre.message.slice(0, -2);
const nextMessages = pre.message?.slice(0, -2) ?? [];
return {
...pre,
message: nextMessages,
@ -441,7 +471,12 @@ export const useSelectCurrentConversation = () => {
}
}, [conversation, conversationId]);
return { currentConversation, addNewestConversation, removeLatestMessage };
return {
currentConversation,
addNewestConversation,
removeLatestMessage,
addNewestAnswer,
};
};
export const useScrollToBottom = (currentConversation: IClientConversation) => {
@ -464,8 +499,12 @@ export const useScrollToBottom = (currentConversation: IClientConversation) => {
export const useFetchConversationOnMount = () => {
const { conversationId } = useGetChatSearchParams();
const fetchConversation = useFetchConversation();
const { currentConversation, addNewestConversation, removeLatestMessage } =
useSelectCurrentConversation();
const {
currentConversation,
addNewestConversation,
removeLatestMessage,
addNewestAnswer,
} = useSelectCurrentConversation();
const ref = useScrollToBottom(currentConversation);
const fetchConversationOnMount = useCallback(() => {
@ -483,6 +522,7 @@ export const useFetchConversationOnMount = () => {
addNewestConversation,
ref,
removeLatestMessage,
addNewestAnswer,
};
};
@ -504,25 +544,22 @@ export const useHandleMessageInputChange = () => {
export const useSendMessage = (
conversation: IClientConversation,
addNewestConversation: (message: string) => void,
addNewestConversation: (message: string, answer?: string) => void,
removeLatestMessage: () => void,
addNewestAnswer: (answer: IAnswer) => void,
) => {
const loading = useOneNamespaceEffectsLoading('chatModel', [
'completeConversation',
]);
const { setConversation } = useSetConversation();
const { conversationId } = useGetChatSearchParams();
const { handleInputChange, value, setValue } = useHandleMessageInputChange();
const fetchConversation = useFetchConversation();
const completeConversation = useCompleteConversation();
const { handleClickConversation } = useClickConversationCard();
// const { send } = useConnectWithSseNext();
const { send, answer, done } = useSendMessageWithSse();
const sendMessage = useCallback(
async (message: string, id?: string) => {
const retcode = await completeConversation({
const res: Response = await send({
conversation_id: id ?? conversationId,
messages: [
...(conversation?.message ?? []).map((x: IMessage) => omit(x, 'id')),
@ -533,27 +570,33 @@ export const useSendMessage = (
],
});
if (retcode === 0) {
if (res.status === 200) {
if (id) {
console.info('111');
// new conversation
handleClickConversation(id);
} else {
fetchConversation(conversationId);
console.info('222');
// fetchConversation(conversationId);
}
} else {
console.info('333');
// cancel loading
setValue(message);
console.info('removeLatestMessage111');
removeLatestMessage();
}
console.info('false');
},
[
conversation?.message,
conversationId,
fetchConversation,
// fetchConversation,
handleClickConversation,
removeLatestMessage,
setValue,
completeConversation,
send,
],
);
@ -572,19 +615,27 @@ export const useSendMessage = (
[conversationId, setConversation, sendMessage],
);
const handlePressEnter = () => {
if (!loading) {
useEffect(() => {
if (answer.answer) {
addNewestAnswer(answer);
console.info('true?');
console.info('send msg:', answer.answer);
}
}, [answer, addNewestAnswer]);
const handlePressEnter = useCallback(() => {
if (done) {
setValue('');
addNewestConversation(value);
handleSendMessage(value.trim());
}
};
addNewestConversation(value);
}, [addNewestConversation, handleSendMessage, done, setValue, value]);
return {
handlePressEnter,
handleInputChange,
value,
loading,
loading: !done,
};
};