feat: add DocumentPreviewer for chunk of chat reference and remove duplicate \n from record.progress_msg (#97)

* feat: Remove duplicate \n from record.progress_msg

* feat: add DocumentPreviewer for chunk of chat reference
This commit is contained in:
balibabu
2024-03-05 16:30:28 +08:00
committed by GitHub
parent 8a57f2afd5
commit 07d76ea18d
14 changed files with 333 additions and 104 deletions

View File

@@ -65,7 +65,11 @@ const AssistantSetting = ({ show }: ISegmentedContentProps) => {
>
<Input placeholder="" />
</Form.Item>
<Form.Item name={['prompt_config', 'prologue']} label="Set an opener">
<Form.Item
name={['prompt_config', 'prologue']}
label="Set an opener"
initialValue={"Hi! I'm your assistant, what can I do for you?"}
>
<Input.TextArea autoSize={{ minRows: 5 }} />
</Form.Item>
<Form.Item

View File

@@ -3,11 +3,21 @@ import { MessageType } from '@/constants/chat';
import { useOneNamespaceEffectsLoading } from '@/hooks/storeHooks';
import { useSelectUserInfo } from '@/hooks/userSettingHook';
import { IReference, Message } from '@/interfaces/database/chat';
import { Avatar, Button, Flex, Input, List, Popover, Space } from 'antd';
import {
Avatar,
Button,
Drawer,
Flex,
Input,
List,
Popover,
Space,
} from 'antd';
import classNames from 'classnames';
import { ChangeEventHandler, useCallback, useMemo, useState } from 'react';
import reactStringReplace from 'react-string-replace';
import {
useClickDrawer,
useFetchConversationOnMount,
useGetFileIcon,
useSendMessage,
@@ -15,7 +25,9 @@ import {
import Image from '@/components/image';
import NewDocumentLink from '@/components/new-document-link';
import DocumentPreviewer from '@/components/pdf-previewer';
import { useSelectFileThumbnails } from '@/hooks/knowledgeHook';
import { IChunk } from '@/interfaces/database/knowledge';
import { InfoCircleOutlined } from '@ant-design/icons';
import Markdown from 'react-markdown';
import { visitParents } from 'unist-util-visit-parents';
@@ -41,15 +53,24 @@ const rehypeWrapReference = () => {
const MessageItem = ({
item,
reference,
clickDocumentButton,
}: {
item: Message;
reference: IReference;
clickDocumentButton: (documentId: string, chunk: IChunk) => void;
}) => {
const userInfo = useSelectUserInfo();
const fileThumbnails = useSelectFileThumbnails();
const isAssistant = item.role === MessageType.Assistant;
const handleDocumentButtonClick = useCallback(
(documentId: string, chunk: IChunk) => () => {
clickDocumentButton(documentId, chunk);
},
[clickDocumentButton],
);
const getPopoverContent = useCallback(
(chunkIndex: number) => {
const chunks = reference?.chunks ?? [];
@@ -83,16 +104,19 @@ const MessageItem = ({
{documentId && (
<Flex gap={'middle'}>
<img src={fileThumbnails[documentId]} alt="" />
<NewDocumentLink documentId={documentId}>
<Button
type="link"
onClick={handleDocumentButtonClick(documentId, chunkItem)}
>
{document?.doc_name}
</NewDocumentLink>
</Button>
</Flex>
)}
</Space>
</Flex>
);
},
[reference, fileThumbnails],
[reference, fileThumbnails, handleDocumentButtonClick],
);
const renderReference = useCallback(
@@ -191,6 +215,8 @@ const ChatContainer = () => {
addNewestConversation,
} = useFetchConversationOnMount();
const { sendMessage } = useSendMessage();
const { visible, hideModal, documentId, selectedChunk, clickDocumentButton } =
useClickDrawer();
const loading = useOneNamespaceEffectsLoading('chatModel', [
'completeConversation',
@@ -210,41 +236,56 @@ const ChatContainer = () => {
};
return (
<Flex flex={1} className={styles.chatContainer} vertical>
<Flex flex={1} vertical className={styles.messageContainer}>
<div>
{conversation?.message?.map((message) => {
const assistantMessages = conversation?.message
?.filter((x) => x.role === MessageType.Assistant)
.slice(1);
const referenceIndex = assistantMessages.findIndex(
(x) => x.id === message.id,
);
const reference = conversation.reference[referenceIndex];
return (
<MessageItem
key={message.id}
item={message}
reference={reference}
></MessageItem>
);
})}
</div>
<div ref={ref} />
<>
<Flex flex={1} className={styles.chatContainer} vertical>
<Flex flex={1} vertical className={styles.messageContainer}>
<div>
{conversation?.message?.map((message) => {
const assistantMessages = conversation?.message
?.filter((x) => x.role === MessageType.Assistant)
.slice(1);
const referenceIndex = assistantMessages.findIndex(
(x) => x.id === message.id,
);
const reference = conversation.reference[referenceIndex];
return (
<MessageItem
key={message.id}
item={message}
reference={reference}
clickDocumentButton={clickDocumentButton}
></MessageItem>
);
})}
</div>
<div ref={ref} />
</Flex>
<Input
size="large"
placeholder="Message Resume Assistant..."
value={value}
suffix={
<Button type="primary" onClick={handlePressEnter} loading={loading}>
Send
</Button>
}
onPressEnter={handlePressEnter}
onChange={handleInputChange}
/>
</Flex>
<Input
size="large"
placeholder="Message Resume Assistant..."
value={value}
suffix={
<Button type="primary" onClick={handlePressEnter} loading={loading}>
Send
</Button>
}
onPressEnter={handlePressEnter}
onChange={handleInputChange}
/>
</Flex>
<Drawer
title="Document Previewer"
onClose={hideModal}
open={visible}
width={'50vw'}
>
<DocumentPreviewer
documentId={documentId}
chunk={selectedChunk}
visible={visible}
></DocumentPreviewer>
</Drawer>
</>
);
};

View File

@@ -4,6 +4,7 @@ import { fileIconMap } from '@/constants/common';
import { useSetModalState } from '@/hooks/commonHooks';
import { useOneNamespaceEffectsLoading } from '@/hooks/storeHooks';
import { IConversation, IDialog } from '@/interfaces/database/chat';
import { IChunk } from '@/interfaces/database/knowledge';
import { getFileExtension } from '@/utils';
import omit from 'lodash/omit';
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
@@ -662,4 +663,28 @@ export const useRenameConversation = () => {
};
};
export const useClickDrawer = () => {
const { visible, showModal, hideModal } = useSetModalState();
const [selectedChunk, setSelectedChunk] = useState<IChunk>({} as IChunk);
const [documentId, setDocumentId] = useState<string>('');
const clickDocumentButton = useCallback(
(documentId: string, chunk: IChunk) => {
showModal();
setSelectedChunk(chunk);
setDocumentId(documentId);
},
[showModal],
);
return {
clickDocumentButton,
visible,
showModal,
hideModal,
selectedChunk,
documentId,
};
};
//#endregion