mirror of
https://github.com/infiniflow/ragflow.git
synced 2025-12-08 20:42:30 +08:00
### What problem does this PR solve? Feat: Create a conversation #3221 ### Type of change - [x] New Feature (non-breaking change which adds functionality)
This commit is contained in:
@ -1,12 +1,12 @@
|
||||
import message from '@/components/ui/message';
|
||||
import { ChatSearchParams } from '@/constants/chat';
|
||||
import { IDialog } from '@/interfaces/database/chat';
|
||||
import chatService from '@/services/chat-service';
|
||||
import chatService from '@/services/next-chat-service ';
|
||||
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
|
||||
import { useDebounce } from 'ahooks';
|
||||
import { useCallback, useMemo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { history, useSearchParams } from 'umi';
|
||||
import { useParams, useSearchParams } from 'umi';
|
||||
import {
|
||||
useGetPaginationWithRouter,
|
||||
useHandleSearchChange,
|
||||
@ -16,6 +16,7 @@ export const enum ChatApiAction {
|
||||
FetchDialogList = 'fetchDialogList',
|
||||
RemoveDialog = 'removeDialog',
|
||||
SetDialog = 'setDialog',
|
||||
FetchDialog = 'fetchDialog',
|
||||
}
|
||||
|
||||
export const useGetChatSearchParams = () => {
|
||||
@ -52,9 +53,7 @@ export const useClickDialogCard = () => {
|
||||
return { handleClickDialog };
|
||||
};
|
||||
|
||||
export const useFetchDialogList = (pureFetch = false) => {
|
||||
const { handleClickDialog } = useClickDialogCard();
|
||||
const { dialogId } = useGetChatSearchParams();
|
||||
export const useFetchDialogList = () => {
|
||||
const { searchString, handleInputChange } = useHandleSearchChange();
|
||||
const { pagination, setPagination } = useGetPaginationWithRouter();
|
||||
const debouncedSearchString = useDebounce(searchString, { wait: 500 });
|
||||
@ -63,7 +62,7 @@ export const useFetchDialogList = (pureFetch = false) => {
|
||||
data,
|
||||
isFetching: loading,
|
||||
refetch,
|
||||
} = useQuery<IDialog[]>({
|
||||
} = useQuery<{ dialogs: IDialog[]; total: number }>({
|
||||
queryKey: [
|
||||
ChatApiAction.FetchDialogList,
|
||||
{
|
||||
@ -71,27 +70,17 @@ export const useFetchDialogList = (pureFetch = false) => {
|
||||
...pagination,
|
||||
},
|
||||
],
|
||||
initialData: [],
|
||||
initialData: { dialogs: [], total: 0 },
|
||||
gcTime: 0,
|
||||
refetchOnWindowFocus: false,
|
||||
queryFn: async (...params) => {
|
||||
console.log('🚀 ~ queryFn: ~ params:', params);
|
||||
const { data } = await chatService.listDialog();
|
||||
queryFn: async () => {
|
||||
const { data } = await chatService.listDialog({
|
||||
keywords: debouncedSearchString,
|
||||
page_size: pagination.pageSize,
|
||||
page: pagination.current,
|
||||
});
|
||||
|
||||
if (data.code === 0) {
|
||||
const list: IDialog[] = data.data;
|
||||
if (!pureFetch) {
|
||||
if (list.length > 0) {
|
||||
if (list.every((x) => x.id !== dialogId)) {
|
||||
handleClickDialog(data.data[0].id);
|
||||
}
|
||||
} else {
|
||||
history.push('/chat');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return data?.data ?? [];
|
||||
return data?.data ?? { dialogs: [], total: 0 };
|
||||
},
|
||||
});
|
||||
|
||||
@ -147,17 +136,14 @@ export const useSetDialog = () => {
|
||||
mutateAsync,
|
||||
} = useMutation({
|
||||
mutationKey: [ChatApiAction.SetDialog],
|
||||
mutationFn: async (params: IDialog) => {
|
||||
mutationFn: async (params: Partial<IDialog>) => {
|
||||
const { data } = await chatService.setDialog(params);
|
||||
if (data.code === 0) {
|
||||
queryClient.invalidateQueries({
|
||||
exact: false,
|
||||
queryKey: ['fetchDialogList'],
|
||||
queryKey: [ChatApiAction.FetchDialogList],
|
||||
});
|
||||
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: ['fetchDialog'],
|
||||
});
|
||||
message.success(
|
||||
t(`message.${params.dialog_id ? 'modified' : 'created'}`),
|
||||
);
|
||||
@ -168,3 +154,29 @@ export const useSetDialog = () => {
|
||||
|
||||
return { data, loading, setDialog: mutateAsync };
|
||||
};
|
||||
|
||||
export const useFetchDialog = () => {
|
||||
const { id } = useParams();
|
||||
|
||||
const {
|
||||
data,
|
||||
isFetching: loading,
|
||||
refetch,
|
||||
} = useQuery<IDialog>({
|
||||
queryKey: [ChatApiAction.FetchDialog, id],
|
||||
gcTime: 0,
|
||||
initialData: {} as IDialog,
|
||||
enabled: !!id,
|
||||
refetchOnWindowFocus: false,
|
||||
queryFn: async () => {
|
||||
const { data } = await chatService.getDialog(
|
||||
{ params: { dialogId: id } },
|
||||
true,
|
||||
);
|
||||
|
||||
return data?.data ?? ({} as IDialog);
|
||||
},
|
||||
});
|
||||
|
||||
return { data, loading, refetch };
|
||||
};
|
||||
|
||||
@ -2,9 +2,9 @@ import { useFetchDialogList } from '@/hooks/use-chat-request';
|
||||
import { ApplicationCard } from './application-card';
|
||||
|
||||
export function ChatList() {
|
||||
const { data } = useFetchDialogList(true);
|
||||
const { data } = useFetchDialogList();
|
||||
|
||||
return data
|
||||
return data.dialogs
|
||||
.slice(0, 10)
|
||||
.map((x) => (
|
||||
<ApplicationCard
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import { PageHeader } from '@/components/page-header';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { useNavigatePage } from '@/hooks/logic-hooks/navigate-hooks';
|
||||
import { useFetchDialog } from '@/hooks/use-chat-request';
|
||||
import { EllipsisVertical } from 'lucide-react';
|
||||
import { AppSettings } from './app-settings';
|
||||
import { ChatBox } from './chat-box';
|
||||
@ -8,10 +9,11 @@ import { Sessions } from './sessions';
|
||||
|
||||
export default function Chat() {
|
||||
const { navigateToChatList } = useNavigatePage();
|
||||
useFetchDialog();
|
||||
|
||||
return (
|
||||
<section className="h-full flex flex-col">
|
||||
<PageHeader back={navigateToChatList} title="Chat app 01">
|
||||
<PageHeader>
|
||||
<div className="flex items-center gap-2">
|
||||
<Button variant={'icon'} size={'icon'}>
|
||||
<EllipsisVertical />
|
||||
|
||||
@ -1,8 +1,33 @@
|
||||
import { useSetModalState } from '@/hooks/common-hooks';
|
||||
import { useSetDialog } from '@/hooks/use-chat-request';
|
||||
import { IDialog } from '@/interfaces/database/chat';
|
||||
import { isEmpty } from 'lodash';
|
||||
import { useCallback, useState } from 'react';
|
||||
|
||||
const InitialData = {
|
||||
name: '',
|
||||
icon: '',
|
||||
language: 'English',
|
||||
prompt_config: {
|
||||
empty_response: '',
|
||||
prologue: '你好! 我是你的助理,有什么可以帮到你的吗?',
|
||||
quote: true,
|
||||
keyword: false,
|
||||
tts: false,
|
||||
system:
|
||||
'你是一个智能助手,请总结知识库的内容来回答问题,请列举知识库中的数据详细回答。当所有知识库内容都与问题无关时,你的回答必须包括“知识库中未找到您要的答案!”这句话。回答需要考虑聊天历史。\n 以下是知识库:\n {knowledge}\n 以上是知识库。',
|
||||
refine_multiturn: false,
|
||||
use_kg: false,
|
||||
reasoning: false,
|
||||
parameters: [{ key: 'knowledge', optional: false }],
|
||||
},
|
||||
llm_id: '',
|
||||
llm_setting: {},
|
||||
similarity_threshold: 0.2,
|
||||
vector_similarity_weight: 0.30000000000000004,
|
||||
top_n: 8,
|
||||
};
|
||||
|
||||
export const useRenameChat = () => {
|
||||
const [chat, setChat] = useState<IDialog>({} as IDialog);
|
||||
const {
|
||||
@ -14,10 +39,11 @@ export const useRenameChat = () => {
|
||||
|
||||
const onChatRenameOk = useCallback(
|
||||
async (name: string) => {
|
||||
const ret = await setDialog({
|
||||
...chat,
|
||||
const nextChat = {
|
||||
...(isEmpty(chat) ? InitialData : chat),
|
||||
name,
|
||||
});
|
||||
};
|
||||
const ret = await setDialog(nextChat);
|
||||
|
||||
if (ret === 0) {
|
||||
hideChatRenameModal();
|
||||
@ -27,19 +53,26 @@ export const useRenameChat = () => {
|
||||
);
|
||||
|
||||
const handleShowChatRenameModal = useCallback(
|
||||
async (record: IDialog) => {
|
||||
setChat(record);
|
||||
(record?: IDialog) => {
|
||||
if (record) {
|
||||
setChat(record);
|
||||
}
|
||||
showChatRenameModal();
|
||||
},
|
||||
[showChatRenameModal],
|
||||
);
|
||||
|
||||
const handleHideModal = useCallback(() => {
|
||||
hideChatRenameModal();
|
||||
setChat({} as IDialog);
|
||||
}, [hideChatRenameModal]);
|
||||
|
||||
return {
|
||||
chatRenameLoading: loading,
|
||||
initialChatName: chat?.name,
|
||||
onChatRenameOk,
|
||||
chatRenameVisible,
|
||||
hideChatRenameModal,
|
||||
hideChatRenameModal: handleHideModal,
|
||||
showChatRenameModal: handleShowChatRenameModal,
|
||||
};
|
||||
};
|
||||
|
||||
@ -11,7 +11,7 @@ import { ChatCard } from './chat-card';
|
||||
import { useRenameChat } from './hooks/use-rename-chat';
|
||||
|
||||
export default function ChatList() {
|
||||
const { data: chatList, setPagination, pagination } = useFetchDialogList();
|
||||
const { data, setPagination, pagination } = useFetchDialogList();
|
||||
const { t } = useTranslation();
|
||||
const {
|
||||
initialChatName,
|
||||
@ -29,11 +29,15 @@ export default function ChatList() {
|
||||
[setPagination],
|
||||
);
|
||||
|
||||
const handleShowCreateModal = useCallback(() => {
|
||||
showChatRenameModal();
|
||||
}, [showChatRenameModal]);
|
||||
|
||||
return (
|
||||
<section className="flex flex-col w-full flex-1">
|
||||
<div className="px-8 pt-8">
|
||||
<ListFilterBar title="Chat apps">
|
||||
<Button>
|
||||
<Button onClick={handleShowCreateModal}>
|
||||
<Plus className="size-2.5" />
|
||||
{t('chat.createChat')}
|
||||
</Button>
|
||||
@ -41,7 +45,7 @@ export default function ChatList() {
|
||||
</div>
|
||||
<div className="flex-1 overflow-auto">
|
||||
<div className="flex flex-wrap gap-4 px-8">
|
||||
{chatList.map((x) => {
|
||||
{data.dialogs.map((x) => {
|
||||
return (
|
||||
<ChatCard
|
||||
key={x.id}
|
||||
@ -65,6 +69,7 @@ export default function ChatList() {
|
||||
onOk={onChatRenameOk}
|
||||
initialName={initialChatName}
|
||||
loading={chatRenameLoading}
|
||||
title={initialChatName || t('chat.createChat')}
|
||||
></RenameDialog>
|
||||
)}
|
||||
</section>
|
||||
|
||||
133
web/src/services/next-chat-service .ts
Normal file
133
web/src/services/next-chat-service .ts
Normal file
@ -0,0 +1,133 @@
|
||||
import api from '@/utils/api';
|
||||
import { registerNextServer } from '@/utils/register-server';
|
||||
|
||||
const {
|
||||
getDialog,
|
||||
setDialog,
|
||||
listDialog,
|
||||
removeDialog,
|
||||
getConversation,
|
||||
getConversationSSE,
|
||||
setConversation,
|
||||
completeConversation,
|
||||
listConversation,
|
||||
removeConversation,
|
||||
createToken,
|
||||
listToken,
|
||||
removeToken,
|
||||
getStats,
|
||||
createExternalConversation,
|
||||
getExternalConversation,
|
||||
completeExternalConversation,
|
||||
uploadAndParseExternal,
|
||||
deleteMessage,
|
||||
thumbup,
|
||||
tts,
|
||||
ask,
|
||||
mindmap,
|
||||
getRelatedQuestions,
|
||||
listNextDialog,
|
||||
} = api;
|
||||
|
||||
const methods = {
|
||||
getDialog: {
|
||||
url: getDialog,
|
||||
method: 'get',
|
||||
},
|
||||
setDialog: {
|
||||
url: setDialog,
|
||||
method: 'post',
|
||||
},
|
||||
removeDialog: {
|
||||
url: removeDialog,
|
||||
method: 'post',
|
||||
},
|
||||
listDialog: {
|
||||
url: listNextDialog,
|
||||
method: 'post',
|
||||
},
|
||||
listConversation: {
|
||||
url: listConversation,
|
||||
method: 'get',
|
||||
},
|
||||
getConversation: {
|
||||
url: getConversation,
|
||||
method: 'get',
|
||||
},
|
||||
getConversationSSE: {
|
||||
url: getConversationSSE,
|
||||
method: 'get',
|
||||
},
|
||||
setConversation: {
|
||||
url: setConversation,
|
||||
method: 'post',
|
||||
},
|
||||
completeConversation: {
|
||||
url: completeConversation,
|
||||
method: 'post',
|
||||
},
|
||||
removeConversation: {
|
||||
url: removeConversation,
|
||||
method: 'post',
|
||||
},
|
||||
createToken: {
|
||||
url: createToken,
|
||||
method: 'post',
|
||||
},
|
||||
listToken: {
|
||||
url: listToken,
|
||||
method: 'get',
|
||||
},
|
||||
removeToken: {
|
||||
url: removeToken,
|
||||
method: 'post',
|
||||
},
|
||||
getStats: {
|
||||
url: getStats,
|
||||
method: 'get',
|
||||
},
|
||||
createExternalConversation: {
|
||||
url: createExternalConversation,
|
||||
method: 'get',
|
||||
},
|
||||
getExternalConversation: {
|
||||
url: getExternalConversation,
|
||||
method: 'get',
|
||||
},
|
||||
completeExternalConversation: {
|
||||
url: completeExternalConversation,
|
||||
method: 'post',
|
||||
},
|
||||
uploadAndParseExternal: {
|
||||
url: uploadAndParseExternal,
|
||||
method: 'post',
|
||||
},
|
||||
deleteMessage: {
|
||||
url: deleteMessage,
|
||||
method: 'post',
|
||||
},
|
||||
thumbup: {
|
||||
url: thumbup,
|
||||
method: 'post',
|
||||
},
|
||||
tts: {
|
||||
url: tts,
|
||||
method: 'post',
|
||||
},
|
||||
ask: {
|
||||
url: ask,
|
||||
method: 'post',
|
||||
},
|
||||
getMindMap: {
|
||||
url: mindmap,
|
||||
method: 'post',
|
||||
},
|
||||
getRelatedQuestions: {
|
||||
url: getRelatedQuestions,
|
||||
method: 'post',
|
||||
},
|
||||
} as const;
|
||||
|
||||
const chatService = registerNextServer<keyof typeof methods>(methods);
|
||||
|
||||
export default chatService;
|
||||
@ -108,6 +108,9 @@ export default {
|
||||
completeExternalConversation: `${api_host}/api/completion`,
|
||||
uploadAndParseExternal: `${api_host}/api/document/upload_and_parse`,
|
||||
|
||||
// next chat
|
||||
listNextDialog: `${api_host}/dialog/next`,
|
||||
|
||||
// file manager
|
||||
listFile: `${api_host}/file/list`,
|
||||
uploadFile: `${api_host}/file/upload`,
|
||||
|
||||
Reference in New Issue
Block a user