diff --git a/web/src/components/new-document-link.tsx b/web/src/components/new-document-link.tsx
new file mode 100644
index 000000000..84c0c9378
--- /dev/null
+++ b/web/src/components/new-document-link.tsx
@@ -0,0 +1,20 @@
+import { api_host } from '@/utils/api';
+import React from 'react';
+
+interface IProps extends React.PropsWithChildren {
+ documentId: string;
+}
+
+const NewDocumentLink = ({ children, documentId }: IProps) => {
+ return (
+
+ {children}
+
+ );
+};
+
+export default NewDocumentLink;
diff --git a/web/src/interfaces/database/chat.ts b/web/src/interfaces/database/chat.ts
index eb4ec51f3..af6b12c90 100644
--- a/web/src/interfaces/database/chat.ts
+++ b/web/src/interfaces/database/chat.ts
@@ -71,7 +71,7 @@ export interface IReference {
total: number;
}
-interface Docagg {
+export interface Docagg {
count: number;
doc_id: string;
doc_name: string;
diff --git a/web/src/pages/add-knowledge/components/knowledge-chunk/components/chunk-card/index.tsx b/web/src/pages/add-knowledge/components/knowledge-chunk/components/chunk-card/index.tsx
index 89af5283b..e509ec0cb 100644
--- a/web/src/pages/add-knowledge/components/knowledge-chunk/components/chunk-card/index.tsx
+++ b/web/src/pages/add-knowledge/components/knowledge-chunk/components/chunk-card/index.tsx
@@ -1,6 +1,5 @@
import Image from '@/components/image';
import { IChunk } from '@/interfaces/database/knowledge';
-import { api_host } from '@/utils/api';
import { Card, Checkbox, CheckboxProps, Flex, Popover, Switch } from 'antd';
import { useState } from 'react';
import styles from './index.less';
@@ -48,11 +47,6 @@ const ChunkCard = ({
}
>
-
)}
diff --git a/web/src/pages/add-knowledge/components/knowledge-testing/testing-result/select-files.tsx b/web/src/pages/add-knowledge/components/knowledge-testing/testing-result/select-files.tsx
index ab5d06c9c..cb80d0175 100644
--- a/web/src/pages/add-knowledge/components/knowledge-testing/testing-result/select-files.tsx
+++ b/web/src/pages/add-knowledge/components/knowledge-testing/testing-result/select-files.tsx
@@ -1,6 +1,6 @@
import { ReactComponent as NavigationPointerIcon } from '@/assets/svg/navigation-pointer.svg';
+import NewDocumentLink from '@/components/new-document-link';
import { ITestingDocument } from '@/interfaces/database/knowledge';
-import { api_host } from '@/utils/api';
import { Table, TableProps } from 'antd';
import { useDispatch, useSelector } from 'umi';
@@ -34,13 +34,9 @@ const SelectFiles = ({ handleTesting }: IProps) => {
key: 'view',
width: 50,
render: (_, { doc_id }) => (
-
+
-
+
),
},
];
diff --git a/web/src/pages/add-knowledge/index.tsx b/web/src/pages/add-knowledge/index.tsx
index 370d1150f..ec4ba5df6 100644
--- a/web/src/pages/add-knowledge/index.tsx
+++ b/web/src/pages/add-knowledge/index.tsx
@@ -2,7 +2,7 @@ import { useKnowledgeBaseId } from '@/hooks/knowledgeHook';
import { useSecondPathName, useThirdPathName } from '@/hooks/routeHook';
import { Breadcrumb } from 'antd';
import { ItemType } from 'antd/es/breadcrumb/Breadcrumb';
-import { useEffect, useMemo } from 'react';
+import { useCallback, useEffect, useMemo } from 'react';
import { Link, Outlet, useDispatch, useLocation, useNavigate } from 'umi';
import Siderbar from './components/knowledge-sidebar';
import {
@@ -25,9 +25,9 @@ const KnowledgeAdding = () => {
const datasetActiveKey: KnowledgeDatasetRouteKey =
useThirdPathName() as KnowledgeDatasetRouteKey;
- const gotoList = () => {
+ const gotoList = useCallback(() => {
navigate('/knowledge');
- };
+ }, [navigate]);
const breadcrumbItems: ItemType[] = useMemo(() => {
const items: ItemType[] = [
@@ -54,7 +54,7 @@ const KnowledgeAdding = () => {
}
return items;
- }, [activeKey, datasetActiveKey]);
+ }, [activeKey, datasetActiveKey, gotoList, knowledgeBaseId]);
useEffect(() => {
const search: string = location.search.slice(1);
@@ -71,7 +71,7 @@ const KnowledgeAdding = () => {
...map,
},
});
- }, [location]);
+ }, [location, dispatch]);
return (
<>
diff --git a/web/src/pages/chat/chat-container/index.less b/web/src/pages/chat/chat-container/index.less
index c0ce04b55..1eba20a51 100644
--- a/web/src/pages/chat/chat-container/index.less
+++ b/web/src/pages/chat/chat-container/index.less
@@ -39,3 +39,11 @@
.messageItemRight {
text-align: right;
}
+
+.referencePopoverWrapper {
+ width: 50vw;
+}
+
+.referenceChunkImage {
+ width: 10vw;
+}
diff --git a/web/src/pages/chat/chat-container/index.tsx b/web/src/pages/chat/chat-container/index.tsx
index 31d939ff5..4f702b80d 100644
--- a/web/src/pages/chat/chat-container/index.tsx
+++ b/web/src/pages/chat/chat-container/index.tsx
@@ -3,18 +3,33 @@ 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, Popover } from 'antd';
+import {
+ Avatar,
+ Button,
+ Flex,
+ Input,
+ List,
+ Popover,
+ Space,
+ Typography,
+} from 'antd';
import classNames from 'classnames';
import { ChangeEventHandler, useCallback, useMemo, useState } from 'react';
import reactStringReplace from 'react-string-replace';
import { useFetchConversation, useSendMessage } from '../hooks';
import { IClientConversation } from '../interface';
+import Image from '@/components/image';
+import NewDocumentLink from '@/components/new-document-link';
import { InfoCircleOutlined } from '@ant-design/icons';
import Markdown from 'react-markdown';
import { visitParents } from 'unist-util-visit-parents';
import styles from './index.less';
+const reg = /(#{2}\d+\${2})/g;
+
+const getChunkIndex = (match: string) => Number(match.slice(2, 3));
+
const rehypeWrapReference = () => {
return function wrapTextTransform(tree: any) {
visitParents(tree, 'text', (node, ancestors) => {
@@ -28,32 +43,67 @@ const rehypeWrapReference = () => {
};
};
-const MessageItem = ({ item }: { item: Message; references: IReference[] }) => {
+const MessageItem = ({
+ item,
+ reference,
+}: {
+ item: Message;
+ reference: IReference;
+}) => {
const userInfo = useSelectUserInfo();
- const popoverContent = useMemo(
- () => (
-
- ),
- [],
+ const isAssistant = item.role === MessageType.Assistant;
+
+ const getPopoverContent = useCallback(
+ (chunkIndex: number) => {
+ const chunks = reference?.chunks ?? [];
+ const chunkItem = chunks[chunkIndex];
+ const document = reference.doc_aggs.find(
+ (x) => x.doc_id === chunkItem.doc_id,
+ );
+ const documentId = document?.doc_id;
+ return (
+
+
+
+ {chunkItem.content_with_weight}
+ {documentId && (
+
+ {document?.doc_name}
+
+ )}
+
+
+ );
+ },
+ [reference],
);
const renderReference = useCallback(
(text: string) => {
- return reactStringReplace(text, /#{2}\d{1,}\${2}/g, (match, i) => {
+ return reactStringReplace(text, reg, (match, i) => {
+ const chunkIndex = getChunkIndex(match);
return (
-
+
);
});
},
- [popoverContent],
+ [getPopoverContent],
);
+ const referenceDocumentList = useMemo(() => {
+ return reference?.doc_aggs ?? [];
+ }, [reference?.doc_aggs]);
+
return (
{
)}
-
- {item.role === MessageType.Assistant ? 'Resume Assistant' : 'You'}
-
+ {isAssistant ? 'Resume Assistant' : 'You'}
{
{item.content}
+ {isAssistant && referenceDocumentList.length > 0 && (
+ (
+
+ [ITEM]
+
+ {item.doc_name}
+
+
+ )}
+ />
+ )}
@@ -131,13 +193,22 @@ const ChatContainer = () => {
- {conversation?.message?.map((message) => (
-
- ))}
+ {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 (
+
+ );
+ })}
{
* */
request.interceptors.response.use(async (response: any, request) => {
- console.log(response, request);
const data: ResponseType = await response.clone().json();
// response 拦截