mirror of
https://github.com/infiniflow/ragflow.git
synced 2025-12-08 20:42:30 +08:00
### What problem does this PR solve? Feat: Modify the data structure of the chunk in the conversation #3909 ### Type of change - [x] New Feature (non-breaking change which adds functionality)
This commit is contained in:
@ -29,18 +29,20 @@ import {
|
||||
useSelectDerivedConversationList,
|
||||
} from './hooks';
|
||||
|
||||
import EmbedModal from '@/components/api-service/embed-modal';
|
||||
import { useShowEmbedModal } from '@/components/api-service/hooks';
|
||||
import SvgIcon from '@/components/svg-icon';
|
||||
import { useTheme } from '@/components/theme-provider';
|
||||
import { SharedFrom } from '@/constants/chat';
|
||||
import {
|
||||
useClickConversationCard,
|
||||
useClickDialogCard,
|
||||
useFetchNextDialogList,
|
||||
useGetChatSearchParams,
|
||||
} from '@/hooks/chat-hooks';
|
||||
import { useSetModalState, useTranslate } from '@/hooks/common-hooks';
|
||||
import { useTranslate } from '@/hooks/common-hooks';
|
||||
import { useSetSelectedRecord } from '@/hooks/logic-hooks';
|
||||
import { IDialog } from '@/interfaces/database/chat';
|
||||
import ChatIdModal from './chat-id-modal';
|
||||
import styles from './index.less';
|
||||
|
||||
const { Text } = Typography;
|
||||
@ -82,13 +84,10 @@ const Chat = () => {
|
||||
showDialogEditModal,
|
||||
} = useEditDialog();
|
||||
const { t } = useTranslate('chat');
|
||||
const {
|
||||
visible: overviewVisible,
|
||||
hideModal: hideOverviewModal,
|
||||
showModal: showOverviewModal,
|
||||
} = useSetModalState();
|
||||
const { currentRecord, setRecord } = useSetSelectedRecord<IDialog>();
|
||||
const [controller, setController] = useState(new AbortController());
|
||||
const { showEmbedModal, hideEmbedModal, embedVisible, beta } =
|
||||
useShowEmbedModal();
|
||||
|
||||
const handleAppCardEnter = (id: string) => () => {
|
||||
handleItemEnter(id);
|
||||
@ -120,7 +119,7 @@ const Chat = () => {
|
||||
info?.domEvent?.preventDefault();
|
||||
info?.domEvent?.stopPropagation();
|
||||
setRecord(dialog);
|
||||
showOverviewModal();
|
||||
showEmbedModal();
|
||||
};
|
||||
|
||||
const handleRemoveConversation =
|
||||
@ -193,7 +192,7 @@ const Chat = () => {
|
||||
label: (
|
||||
<Space>
|
||||
<KeyOutlined />
|
||||
{t('overview')}
|
||||
{t('publish', { keyPrefix: 'flow' })}
|
||||
</Space>
|
||||
),
|
||||
},
|
||||
@ -374,14 +373,16 @@ const Chat = () => {
|
||||
initialName={initialConversationName}
|
||||
loading={conversationRenameLoading}
|
||||
></RenameModal>
|
||||
{overviewVisible && (
|
||||
<ChatIdModal
|
||||
visible={overviewVisible}
|
||||
hideModal={hideOverviewModal}
|
||||
id={currentRecord.id}
|
||||
name={currentRecord.name}
|
||||
idKey="dialogId"
|
||||
></ChatIdModal>
|
||||
|
||||
{embedVisible && (
|
||||
<EmbedModal
|
||||
visible={embedVisible}
|
||||
hideModal={hideEmbedModal}
|
||||
token={currentRecord.id}
|
||||
form={SharedFrom.Chat}
|
||||
beta={beta}
|
||||
isAgent={false}
|
||||
></EmbedModal>
|
||||
)}
|
||||
</Flex>
|
||||
);
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
import Image from '@/components/image';
|
||||
import SvgIcon from '@/components/svg-icon';
|
||||
import { IReference } from '@/interfaces/database/chat';
|
||||
import { IChunk } from '@/interfaces/database/knowledge';
|
||||
import { IReference, IReferenceChunk } from '@/interfaces/database/chat';
|
||||
import { getExtension } from '@/utils/document-util';
|
||||
import { InfoCircleOutlined } from '@ant-design/icons';
|
||||
import { Button, Flex, Popover, Space } from 'antd';
|
||||
@ -11,6 +10,7 @@ import Markdown from 'react-markdown';
|
||||
import reactStringReplace from 'react-string-replace';
|
||||
import SyntaxHighlighter from 'react-syntax-highlighter';
|
||||
import rehypeKatex from 'rehype-katex';
|
||||
import rehypeRaw from 'rehype-raw';
|
||||
import remarkGfm from 'remark-gfm';
|
||||
import remarkMath from 'remark-math';
|
||||
import { visitParents } from 'unist-util-visit-parents';
|
||||
@ -36,7 +36,7 @@ const MarkdownContent = ({
|
||||
content: string;
|
||||
loading: boolean;
|
||||
reference: IReference;
|
||||
clickDocumentButton?: (documentId: string, chunk: IChunk) => void;
|
||||
clickDocumentButton?: (documentId: string, chunk: IReferenceChunk) => void;
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
const { setDocumentIds, data: fileThumbnails } =
|
||||
@ -54,7 +54,7 @@ const MarkdownContent = ({
|
||||
}, [reference, setDocumentIds]);
|
||||
|
||||
const handleDocumentButtonClick = useCallback(
|
||||
(documentId: string, chunk: IChunk, isPdf: boolean) => () => {
|
||||
(documentId: string, chunk: IReferenceChunk, isPdf: boolean) => () => {
|
||||
if (!isPdf) {
|
||||
return;
|
||||
}
|
||||
@ -85,15 +85,15 @@ const MarkdownContent = ({
|
||||
const chunks = reference?.chunks ?? [];
|
||||
const chunkItem = chunks[chunkIndex];
|
||||
const document = reference?.doc_aggs?.find(
|
||||
(x) => x?.doc_id === chunkItem?.doc_id,
|
||||
(x) => x?.doc_id === chunkItem?.document_id,
|
||||
);
|
||||
const documentId = document?.doc_id;
|
||||
const fileThumbnail = documentId ? fileThumbnails[documentId] : '';
|
||||
const fileExtension = documentId ? getExtension(document?.doc_name) : '';
|
||||
const imageId = chunkItem?.img_id;
|
||||
const imageId = chunkItem?.image_id;
|
||||
return (
|
||||
<Flex
|
||||
key={chunkItem?.chunk_id}
|
||||
key={chunkItem?.id}
|
||||
gap={10}
|
||||
className={styles.referencePopoverWrapper}
|
||||
>
|
||||
@ -116,7 +116,7 @@ const MarkdownContent = ({
|
||||
<Space direction={'vertical'}>
|
||||
<div
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: DOMPurify.sanitize(chunkItem?.content_with_weight),
|
||||
__html: DOMPurify.sanitize(chunkItem?.content ?? ''),
|
||||
}}
|
||||
className={styles.chunkContentText}
|
||||
></div>
|
||||
@ -176,7 +176,7 @@ const MarkdownContent = ({
|
||||
|
||||
return (
|
||||
<Markdown
|
||||
rehypePlugins={[rehypeWrapReference, rehypeKatex]}
|
||||
rehypePlugins={[rehypeWrapReference, rehypeKatex, rehypeRaw]}
|
||||
remarkPlugins={[remarkGfm, remarkMath]}
|
||||
components={
|
||||
{
|
||||
|
||||
@ -1,21 +1,23 @@
|
||||
import MessageInput from '@/components/message-input';
|
||||
import MessageItem from '@/components/message-item';
|
||||
import { useClickDrawer } from '@/components/pdf-drawer/hooks';
|
||||
import { MessageType, SharedFrom } from '@/constants/chat';
|
||||
import { useFetchNextSharedConversation } from '@/hooks/chat-hooks';
|
||||
import { useSendButtonDisabled } from '@/pages/chat/hooks';
|
||||
import { Flex, Spin } from 'antd';
|
||||
import { forwardRef } from 'react';
|
||||
import {
|
||||
useCreateSharedConversationOnMount,
|
||||
useGetSharedChatSearchParams,
|
||||
useSendSharedMessage,
|
||||
} from '../shared-hooks';
|
||||
import { buildMessageItemReference } from '../utils';
|
||||
|
||||
import PdfDrawer from '@/components/pdf-drawer';
|
||||
import styles from './index.less';
|
||||
|
||||
const ChatContainer = () => {
|
||||
const { conversationId } = useCreateSharedConversationOnMount();
|
||||
const { data } = useFetchNextSharedConversation(conversationId);
|
||||
const { from, sharedId: conversationId } = useGetSharedChatSearchParams();
|
||||
const { visible, hideModal, documentId, selectedChunk, clickDocumentButton } =
|
||||
useClickDrawer();
|
||||
|
||||
const {
|
||||
handlePressEnter,
|
||||
@ -25,9 +27,13 @@ const ChatContainer = () => {
|
||||
loading,
|
||||
ref,
|
||||
derivedMessages,
|
||||
} = useSendSharedMessage(conversationId);
|
||||
hasError,
|
||||
} = useSendSharedMessage();
|
||||
const sendDisabled = useSendButtonDisabled(value);
|
||||
const { from } = useGetSharedChatSearchParams();
|
||||
|
||||
if (!conversationId) {
|
||||
return <div>empty</div>;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
@ -44,7 +50,7 @@ const ChatContainer = () => {
|
||||
reference={buildMessageItemReference(
|
||||
{
|
||||
message: derivedMessages,
|
||||
reference: data?.data?.reference,
|
||||
reference: [],
|
||||
},
|
||||
message,
|
||||
)}
|
||||
@ -54,6 +60,7 @@ const ChatContainer = () => {
|
||||
derivedMessages?.length - 1 === i
|
||||
}
|
||||
index={i}
|
||||
clickDocumentButton={clickDocumentButton}
|
||||
></MessageItem>
|
||||
);
|
||||
})}
|
||||
@ -65,7 +72,7 @@ const ChatContainer = () => {
|
||||
<MessageInput
|
||||
isShared
|
||||
value={value}
|
||||
disabled={false}
|
||||
disabled={hasError}
|
||||
sendDisabled={sendDisabled}
|
||||
conversationId={conversationId}
|
||||
onInputChange={handleInputChange}
|
||||
@ -75,6 +82,14 @@ const ChatContainer = () => {
|
||||
showUploadIcon={from === SharedFrom.Chat}
|
||||
></MessageInput>
|
||||
</Flex>
|
||||
{visible && (
|
||||
<PdfDrawer
|
||||
visible={visible}
|
||||
hideModal={hideModal}
|
||||
documentId={documentId}
|
||||
chunk={selectedChunk}
|
||||
></PdfDrawer>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
@ -1,83 +1,41 @@
|
||||
import { MessageType, SharedFrom } from '@/constants/chat';
|
||||
import {
|
||||
useCreateNextSharedConversation,
|
||||
useFetchNextSharedConversation,
|
||||
} from '@/hooks/chat-hooks';
|
||||
import { useCreateNextSharedConversation } from '@/hooks/chat-hooks';
|
||||
import {
|
||||
useSelectDerivedMessages,
|
||||
useSendMessageWithSse,
|
||||
} from '@/hooks/logic-hooks';
|
||||
import { Message } from '@/interfaces/database/chat';
|
||||
import api from '@/utils/api';
|
||||
import { message } from 'antd';
|
||||
import { get } from 'lodash';
|
||||
import trim from 'lodash/trim';
|
||||
import { useCallback, useEffect, useState } from 'react';
|
||||
import { useSearchParams } from 'umi';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
import { useHandleMessageInputChange } from './hooks';
|
||||
|
||||
export const useCreateSharedConversationOnMount = () => {
|
||||
const [currentQueryParameters] = useSearchParams();
|
||||
const [conversationId, setConversationId] = useState('');
|
||||
|
||||
const { createSharedConversation: createConversation } =
|
||||
useCreateNextSharedConversation();
|
||||
const sharedId = currentQueryParameters.get('shared_id');
|
||||
const userId = currentQueryParameters.get('user_id');
|
||||
|
||||
const setConversation = useCallback(async () => {
|
||||
if (sharedId) {
|
||||
const data = await createConversation(userId ?? undefined);
|
||||
const id = data.data?.id;
|
||||
if (id) {
|
||||
setConversationId(id);
|
||||
}
|
||||
}
|
||||
}, [createConversation, sharedId, userId]);
|
||||
|
||||
useEffect(() => {
|
||||
setConversation();
|
||||
}, [setConversation]);
|
||||
|
||||
return { conversationId };
|
||||
};
|
||||
|
||||
export const useSelectNextSharedMessages = (conversationId: string) => {
|
||||
const { data, loading } = useFetchNextSharedConversation(conversationId);
|
||||
|
||||
const {
|
||||
derivedMessages,
|
||||
ref,
|
||||
setDerivedMessages,
|
||||
addNewestAnswer,
|
||||
addNewestQuestion,
|
||||
removeLatestMessage,
|
||||
} = useSelectDerivedMessages();
|
||||
|
||||
useEffect(() => {
|
||||
setDerivedMessages(data?.data?.message);
|
||||
}, [setDerivedMessages, data]);
|
||||
|
||||
return {
|
||||
derivedMessages,
|
||||
addNewestAnswer,
|
||||
addNewestQuestion,
|
||||
removeLatestMessage,
|
||||
loading,
|
||||
ref,
|
||||
setDerivedMessages,
|
||||
};
|
||||
};
|
||||
const isCompletionError = (res: any) =>
|
||||
res && (res?.response.status !== 200 || res?.data?.code !== 0);
|
||||
|
||||
export const useSendButtonDisabled = (value: string) => {
|
||||
return trim(value) === '';
|
||||
};
|
||||
|
||||
export const useSendSharedMessage = (conversationId: string) => {
|
||||
export const useGetSharedChatSearchParams = () => {
|
||||
const [searchParams] = useSearchParams();
|
||||
|
||||
return {
|
||||
from: searchParams.get('from') as SharedFrom,
|
||||
sharedId: searchParams.get('shared_id'),
|
||||
};
|
||||
};
|
||||
|
||||
export const useSendSharedMessage = () => {
|
||||
const { from, sharedId: conversationId } = useGetSharedChatSearchParams();
|
||||
const { createSharedConversation: setConversation } =
|
||||
useCreateNextSharedConversation();
|
||||
const { handleInputChange, value, setValue } = useHandleMessageInputChange();
|
||||
const { send, answer, done } = useSendMessageWithSse(
|
||||
api.completeExternalConversation,
|
||||
`/api/v1/${from === SharedFrom.Agent ? 'agentbots' : 'chatbots'}/${conversationId}/completions`,
|
||||
);
|
||||
const {
|
||||
derivedMessages,
|
||||
@ -85,24 +43,25 @@ export const useSendSharedMessage = (conversationId: string) => {
|
||||
removeLatestMessage,
|
||||
addNewestAnswer,
|
||||
addNewestQuestion,
|
||||
loading,
|
||||
} = useSelectNextSharedMessages(conversationId);
|
||||
} = useSelectDerivedMessages();
|
||||
const [hasError, setHasError] = useState(false);
|
||||
|
||||
const sendMessage = useCallback(
|
||||
async (message: Message, id?: string) => {
|
||||
const res = await send({
|
||||
conversation_id: id ?? conversationId,
|
||||
quote: false,
|
||||
messages: [...(derivedMessages ?? []), message],
|
||||
quote: true,
|
||||
question: message.content,
|
||||
session_id: get(derivedMessages, '0.session_id'),
|
||||
});
|
||||
|
||||
if (res && (res?.response.status !== 200 || res?.data?.code !== 0)) {
|
||||
if (isCompletionError(res)) {
|
||||
// cancel loading
|
||||
setValue(message.content);
|
||||
removeLatestMessage();
|
||||
}
|
||||
},
|
||||
[conversationId, derivedMessages, removeLatestMessage, setValue, send],
|
||||
[send, conversationId, derivedMessages, setValue, removeLatestMessage],
|
||||
);
|
||||
|
||||
const handleSendMessage = useCallback(
|
||||
@ -120,6 +79,18 @@ export const useSendSharedMessage = (conversationId: string) => {
|
||||
[conversationId, setConversation, sendMessage],
|
||||
);
|
||||
|
||||
const fetchSessionId = useCallback(async () => {
|
||||
const ret = await send({ question: '' });
|
||||
if (isCompletionError(ret)) {
|
||||
message.error(ret?.data.message);
|
||||
setHasError(true);
|
||||
}
|
||||
}, [send]);
|
||||
|
||||
useEffect(() => {
|
||||
fetchSessionId();
|
||||
}, [fetchSessionId, send]);
|
||||
|
||||
useEffect(() => {
|
||||
if (answer.answer) {
|
||||
addNewestAnswer(answer);
|
||||
@ -154,16 +125,8 @@ export const useSendSharedMessage = (conversationId: string) => {
|
||||
value,
|
||||
sendLoading: !done,
|
||||
ref,
|
||||
loading,
|
||||
loading: false,
|
||||
derivedMessages,
|
||||
};
|
||||
};
|
||||
|
||||
export const useGetSharedChatSearchParams = () => {
|
||||
const [searchParams] = useSearchParams();
|
||||
|
||||
return {
|
||||
from: searchParams.get('from') as SharedFrom,
|
||||
sharedId: searchParams.get('shared_id'),
|
||||
hasError,
|
||||
};
|
||||
};
|
||||
|
||||
@ -1,13 +1,15 @@
|
||||
import ChatOverviewModal from '@/components/api-service/chat-overview-modal';
|
||||
import { useSetModalState, useTranslate } from '@/hooks/common-hooks';
|
||||
import EmbedModal from '@/components/api-service/embed-modal';
|
||||
import { useShowEmbedModal } from '@/components/api-service/hooks';
|
||||
import { SharedFrom } from '@/constants/chat';
|
||||
import { useTranslate } from '@/hooks/common-hooks';
|
||||
import { useFetchFlow } from '@/hooks/flow-hooks';
|
||||
import { ArrowLeftOutlined } from '@ant-design/icons';
|
||||
import { Button, Flex, Space } from 'antd';
|
||||
import { useCallback } from 'react';
|
||||
import { Link, useParams } from 'umi';
|
||||
import FlowIdModal from '../flow-id-modal';
|
||||
import {
|
||||
useGetBeginNodeDataQuery,
|
||||
useGetBeginNodeDataQueryIsEmpty,
|
||||
useSaveGraph,
|
||||
useSaveGraphBeforeOpeningDebugDrawer,
|
||||
useWatchAgentChange,
|
||||
@ -25,15 +27,16 @@ const FlowHeader = ({ showChatDrawer, chatDrawerVisible }: IProps) => {
|
||||
const { handleRun } = useSaveGraphBeforeOpeningDebugDrawer(showChatDrawer);
|
||||
const { data } = useFetchFlow();
|
||||
const { t } = useTranslate('flow');
|
||||
const {
|
||||
visible: overviewVisible,
|
||||
hideModal: hideOverviewModal,
|
||||
// showModal: showOverviewModal,
|
||||
} = useSetModalState();
|
||||
const { visible, hideModal, showModal } = useSetModalState();
|
||||
const { id } = useParams();
|
||||
const time = useWatchAgentChange(chatDrawerVisible);
|
||||
const getBeginNodeDataQuery = useGetBeginNodeDataQuery();
|
||||
const { showEmbedModal, hideEmbedModal, embedVisible, beta } =
|
||||
useShowEmbedModal();
|
||||
const isBeginNodeDataQueryEmpty = useGetBeginNodeDataQueryIsEmpty();
|
||||
|
||||
const handleShowEmbedModal = useCallback(() => {
|
||||
showEmbedModal();
|
||||
}, [showEmbedModal]);
|
||||
|
||||
const handleRunAgent = useCallback(() => {
|
||||
const query: BeginQuery[] = getBeginNodeDataQuery();
|
||||
@ -70,23 +73,25 @@ const FlowHeader = ({ showChatDrawer, chatDrawerVisible }: IProps) => {
|
||||
<Button type="primary" onClick={() => saveGraph()}>
|
||||
<b>{t('save')}</b>
|
||||
</Button>
|
||||
{/* <Button type="primary" onClick={showOverviewModal} disabled>
|
||||
<Button
|
||||
type="primary"
|
||||
onClick={handleShowEmbedModal}
|
||||
disabled={!isBeginNodeDataQueryEmpty}
|
||||
>
|
||||
<b>{t('publish')}</b>
|
||||
</Button> */}
|
||||
<Button type="primary" onClick={showModal}>
|
||||
<b>Agent ID</b>
|
||||
</Button>
|
||||
</Space>
|
||||
</Flex>
|
||||
{overviewVisible && (
|
||||
<ChatOverviewModal
|
||||
visible={overviewVisible}
|
||||
hideModal={hideOverviewModal}
|
||||
id={id!}
|
||||
idKey="canvasId"
|
||||
></ChatOverviewModal>
|
||||
{embedVisible && (
|
||||
<EmbedModal
|
||||
visible={embedVisible}
|
||||
hideModal={hideEmbedModal}
|
||||
token={id!}
|
||||
form={SharedFrom.Agent}
|
||||
beta={beta}
|
||||
isAgent
|
||||
></EmbedModal>
|
||||
)}
|
||||
{visible && <FlowIdModal hideModal={hideModal}></FlowIdModal>}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
@ -474,6 +474,20 @@ export const useGetBeginNodeDataQuery = () => {
|
||||
return getBeginNodeDataQuery;
|
||||
};
|
||||
|
||||
export const useGetBeginNodeDataQueryIsEmpty = () => {
|
||||
const [isBeginNodeDataQueryEmpty, setIsBeginNodeDataQueryEmpty] =
|
||||
useState(false);
|
||||
const getBeginNodeDataQuery = useGetBeginNodeDataQuery();
|
||||
const nodes = useGraphStore((state) => state.nodes);
|
||||
|
||||
useEffect(() => {
|
||||
const query: BeginQuery[] = getBeginNodeDataQuery();
|
||||
setIsBeginNodeDataQueryEmpty(query.length === 0);
|
||||
}, [getBeginNodeDataQuery, nodes]);
|
||||
|
||||
return isBeginNodeDataQueryEmpty;
|
||||
};
|
||||
|
||||
export const useSaveGraphBeforeOpeningDebugDrawer = (show: () => void) => {
|
||||
const { saveGraph, loading } = useSaveGraph();
|
||||
const { resetFlow } = useResetFlow();
|
||||
|
||||
Reference in New Issue
Block a user